     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.0.22
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; NASM version 2.15 (unix386.s)
     5                                  ;
     6                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     7                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
     8                                  ;
     9                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    10                                  ; (v0.1 - Beginning: 11/07/2012)
    11                                  ;
    12                                  ; [ Last Modification: 24/07/2022 ] ; 2022 modification (previous: 12/7/2022)
    13                                  ;
    14                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    15                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    16                                  ; <Bell Laboratories (17/3/1972)>
    17                                  ; <Preliminary Release of UNIX Implementation Document>
    18                                  ;
    19                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    20                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    21                                  ;
    22                                  ; ****************************************************************************
    23                                  ; 14/07/2022 - 24/07/2022 (v0.2.0.22)
    24                                  ; 12/07/2022 (v0.2.0.21)
    25                                  ; 15/05/2022 - 14/06/2022 (v0.2.0.20) 
    26                                  ; 04/02/2016 (v0.2.0.17) - 29/04/2022 (v0.2.0.18) - 09/05/2022 (v0.2.0.19)
    27                                  
    28                                  ; Assembler: NASM 2.15
    29                                  ;	nasm unix386.s -l unix386.lst -o unix386 -Z error.txt
    30                                  
    31                                  ; 24/12/2013
    32                                  
    33                                  ; Entering protected mode:
    34                                  ; Derived from 'simple_asm.txt' source code file and 
    35                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    36                                  ; (gregor.brunmar@home.se)
    37                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    38                                  ;
    39                                  
    40                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    41                                  ; by Michael Chourdakis (2009) 
    42                                  ; http://www.codeproject.com/Articles/45788/
    43                                  ; http://www.michaelchourdakis.com
    44                                  ;
    45                                  
    46                                  ; Global Descriptor Table:
    47                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    48                                  ; by Linus Torvalds (1991-1992)
    49                                  ;
    50                                  
    51                                  KLOAD	equ 10000h ; Kernel loading address
    52                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 
    53                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    54                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    55                                  ; 19/03/2015
    56                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    57                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    58                                  ; 24/03/2015
    59                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    60                                  ; 19/03/2015
    61                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    62                                  		     ; (at the end of the 1st 4MB)
    63                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    64                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    65                                  
    66                                  ; 27/12/2013
    67                                  KEND    equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    68                                  
    69                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    70                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    71                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    72                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    73                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    74                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    75                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    76                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    77                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    78                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    79                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    80                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    81                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    82                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    83                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    84                                  ;----------------------------------------
    85                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    86                                  ;-----------------------------------------------------------------------------
    87                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    88                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    89                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    90                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    91                                  
    92                                  ; Memory Allocation Table Address
    93                                  ; 05/11/2014
    94                                  ; 31/10/2014
    95                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    96                                  					; the 1st 1 MB memory space.
    97                                  					; (This address must be aligned
    98                                  					;  on 128 KB boundary, if it will be
    99                                  					;  changed later.)
   100                                  					; ((lower 17 bits of 32 bit M.A.T.
   101                                  					;   address must be ZERO)).
   102                                  					; ((((Reason: 32 bit allocation 
   103                                  					;     instructions, dword steps)))
   104                                  					; (((byte >> 12 --> page >> 5)))  
   105                                  ;04/11/2014	
   106                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   107                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   108                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   109                                  ;
   110                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   111                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   112                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   113                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   114                                  
   115                                  ; 17/02/2015 (unix386.s)
   116                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   117                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   118                                  ;
   119                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   120                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   121                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   122                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   123                                  
   124                                  
   125                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   126                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   127                                  ;
   128                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   129                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   130                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   131                                  		      ; otherwise it is standard FDPT with physical values 	
   132                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   133                                  		      ; (obsolete for IDE/ATA drives)
   134                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   135                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   136                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   137                                  			; Bit 4 : Reserved. Always 0
   138                                  			; Bit 3 : Set to 1 if more than 8 heads
   139                                  			; Bit 2-0 : Reserved. Alsways 0
   140                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   141                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   142                                  
   143                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   144                                  ; (11 bytes long) will be used by diskette handler/bios
   145                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   146                                  
   147                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   148                                  
   149                                  [ORG 0] 
   150                                  	; 12/11/2014
   151                                  	; Save boot drive number (that is default root drive)
   152 00000000 8816[585C]              	mov	[boot_drv], dl ; physical drv number
   153                                  
   154                                  	; Determine installed memory
   155                                  	; 31/10/2014
   156                                  	;
   157 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   158 00000007 CD15                    	int	15h	   ; for large configurations
   159 00000009 7308                    	jnc	short chk_ms
   160 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   161 0000000D CD15                    	int	15h
   162                                  	;	   
   163                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   164                                  	;out	70h, al ; select CMOS register
   165                                  	;in	al, 71h ; read data (1 byte)
   166                                  	;mov	cl, al
   167                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   168                                  	;out	70h, al ; select CMOS register
   169                                  	;in	al, 71h ; read data (1 byte)
   170                                  	;mov	ch, al
   171                                   	;      
   172 0000000F 89C1                    	mov	cx, ax
   173 00000011 31D2                    	xor	dx, dx
   174                                  chk_ms:
   175 00000013 890E[C25E]              	mov	[mem_1m_1k], cx
   176 00000017 8916[C45E]              	mov	[mem_16m_64k], dx
   177                                  	; 05/11/2014
   178                                  	;and	dx, dx
   179                                  	;jz	short L2
   180 0000001B 81F90004                        cmp     cx, 1024
   181 0000001F 7351                    	jnb	short L0
   182                                  		 ; insufficient memory_error	
   183                                  		 ; Minimum 2 MB memory is needed... 
   184                                  	; 05/11/2014
   185                                  	; (real mode error printing)
   186 00000021 FB                      	sti
   187 00000022 BE[3600]                	mov	si, msg_out_of_memory
   188 00000025 BB0700                  	mov	bx, 7
   189 00000028 B40E                    	mov	ah, 0Eh	; write tty
   190                                  oom_1:
   191 0000002A AC                      	lodsb
   192 0000002B 08C0                    	or	al, al
   193 0000002D 7404                    	jz	short oom_2
   194 0000002F CD10                    	int	10h
   195 00000031 EBF7                    	jmp	short oom_1
   196                                  oom_2:
   197 00000033 F4                              hlt
   198 00000034 EBFD                    	jmp	short oom_2
   199                                  
   200                                  ; 04/02/2022
   201                                  ; 05/11/2014
   202                                  msg_out_of_memory:
   203 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   204 00000039 496E73756666696369-             db      'Insufficient memory !'
   204 00000042 656E74206D656D6F72-
   204 0000004B 792021             
   205 0000004E 0D0A                    	db	0Dh, 0Ah
   206                                  _int13h_48h_buffer: 
   207                                  	; 04/02/2022 (Runix Kernel v0.2.0.18, 'diskinit.inc')
   208 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   208 00000059 324D42206D656D6F72-
   208 00000062 79206973206E656564-
   208 0000006B 65642E29           
   209 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   210                                  
   211                                  L0:
   212                                  %include 'diskinit.inc' ; 07/03/2015
   213                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKINIT.INC
   214                              <1> ; Last Modification: 12/07/2022
   215                              <1> ; ************************************************************************
   216                              <1> ; Ref: Retro UNIX 386 v1.1 'diskinit.inc' modification: 12/07/2022
   217                              <1> 
   218                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   219                              <1> 
   220                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   221                              <1> 
   222                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Runix Kernel v0.2.0.18)
   223                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   224                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   225                              <1> ;L0:
   226                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   227                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   228 00000072 BA7F00              <1> 	mov	dx, 7Fh
   229                              <1> L1:	
   230 00000075 FEC2                <1> 	inc	dl
   231 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   232                              <1> 			; Phoenix EDD v1.1 - EDD v3
   233 00000079 BBAA55              <1> 	mov	bx, 55AAh
   234 0000007C CD13                <1> 	int 	13h
   235 0000007E 721A                <1> 	jc	short L2
   236                              <1> 
   237 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   238 00000084 7514                <1> 	jne	short L2
   239 00000086 FE06[5B5C]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   240 0000008A 8816[5A5C]          <1>         mov     [last_drv], dl  ; last hard disk number
   241 0000008E BB[DE5B]            <1> 	mov	bx, hd0_type - 80h
   242 00000091 01D3                <1> 	add	bx, dx	 
   243 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   244                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   245                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   246                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   247                              <1>                          ;            (EDD) ready (DPTE ready)
   248                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   249                              <1>                          ;            (EDD-3)
   250                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   251 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   252 00000098 72DB                <1> 	jb	short L1
   253                              <1> L2:
   254                              <1> 	; 23/11/2014
   255                              <1> 	; 19/11/2014
   256 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   257                              <1> 	; 04/02/2016 (esi -> si)
   258 0000009C BE[5C5C]            <1> 	mov	si, fd0_type
   259                              <1> L3:
   260                              <1> 	; 14/01/2015
   261 0000009F 8816[595C]          <1> 	mov	[drv], dl
   262                              <1> 	;
   263 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   264 000000A5 CD13                <1> 	int	13h	
   265 000000A7 7210                <1> 	jc	short L4
   266                              <1> 		; BL = drive type (for floppy drives)
   267                              <1> 		; DL = number of floppy drives
   268                              <1> 		;		
   269                              <1> 		; ES:DI = Address of DPT from BIOS
   270                              <1> 		;
   271 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   272                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   273                              <1> 	; 14/01/2015
   274 000000AB E8BB01              <1> 	call	set_disk_parms
   275                              <1> 	; 10/12/2014
   276 000000AE 81FE[5C5C]          <1> 	cmp	si, fd0_type
   277 000000B2 7705                <1> 	ja	short L4
   278 000000B4 46                  <1> 	inc	si ; fd1_type
   279 000000B5 B201                <1> 	mov	dl, 1
   280 000000B7 EBE6                <1> 	jmp	short L3
   281                              <1> L4:
   282                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   283 000000B9 B27F                <1> 	mov	dl, 7Fh
   284                              <1> 	; 24/12/2014 (Temporary)
   285 000000BB 803E[5B5C]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   286                              <1> 	;ja	L10       ; yes, all fixed disk operations
   287                              <1> 			  ; will be performed according to
   288                              <1> 			  ; present EDD specification
   289                              <1> 	; 02/01/2022
   290 000000C0 7603                <1> 	jna	short L5
   291 000000C2 E99100              <1> 	jmp	L10
   292                              <1> L5:
   293 000000C5 FEC2                <1> 	inc 	dl
   294 000000C7 8816[595C]          <1>         mov     [drv], dl
   295 000000CB 8816[5A5C]          <1>         mov     [last_drv], dl ; 14/01/2015
   296 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   297 000000D1 CD13                <1> 	int	13h	; (conventional function)
   298                              <1> 	;jc	L13	; fixed disk drive not ready
   299                              <1> 	; 02/01/2022
   300 000000D3 7303                <1> 	jnc	short L6
   301 000000D5 E98301              <1> 	jmp	L13
   302                              <1> L6:
   303 000000D8 8816[5B5C]          <1>         mov     [hdc], dl ; number of drives
   304                              <1> 	;; 14/01/2013
   305                              <1> 	;;push	cx
   306 000000DC E88A01              <1> 	call	set_disk_parms
   307                              <1> 	;;pop	cx
   308                              <1> 	;
   309                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   310 000000DF 8A16[595C]          <1>         mov     dl, [drv]
   311 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   312 000000E6 80FA80              <1> 	cmp	dl, 80h
   313 000000E9 7603                <1> 	jna	short L7
   314 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   315                              <1> L7:	
   316 000000EE 31C0                <1> 	xor	ax, ax
   317 000000F0 8ED8                <1> 	mov	ds, ax
   318 000000F2 8B37                <1>         mov     si, [bx]
   319 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   320 000000F7 8ED8                <1> 	mov	ds, ax
   321 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   322                              <1> 	;jne	L12 ; invalid FDPT
   323                              <1> 	; 02/01/2022
   324 000000FC 7403                <1> 	je	short L7_8
   325 000000FE E95601              <1> 	jmp	L12
   326                              <1> L7_8:
   327 00000101 BF0000              <1> 	mov	di, HD0_DPT
   328 00000104 80FA80              <1> 	cmp	dl, 80h
   329 00000107 7603                <1> 	jna	short L8
   330 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   331                              <1> L8:
   332                              <1> 	; 30/12/2014
   333 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   334 0000010F 8EC0                <1> 	mov	es, ax
   335                              <1> 	; 24/12/2014
   336 00000111 B90800              <1> 	mov	cx, 8
   337 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   338 00000116 8CC8                <1> 	mov	ax, cs
   339 00000118 8ED8                <1> 	mov	ds, ax
   340                              <1> 	; 02/02/2015
   341 0000011A 8A0E[595C]          <1>         mov     cl, [drv]
   342 0000011E 88CB                <1> 	mov	bl, cl
   343 00000120 B8F001              <1> 	mov	ax, 1F0h
   344 00000123 80E301              <1> 	and	bl, 1
   345 00000126 7406                <1> 	jz	short L9
   346 00000128 C0E304              <1> 	shl	bl, 4
   347 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   348                              <1> L9:
   349 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   350 0000012F 050602              <1> 	add	ax, 206h
   351 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   352 00000133 88D8                <1> 	mov	al, bl
   353 00000135 04A0                <1> 	add	al, 0A0h
   354 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   355                              <1> 	;
   356 00000138 FE06[595C]          <1> 	inc	byte [drv]
   357 0000013C BB[DE5B]            <1> 	mov	bx, hd0_type - 80h
   358 0000013F 01CB                <1> 	add	bx, cx
   359 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   360 00000144 A0[5B5C]            <1> 	mov	al, [hdc]
   361 00000147 FEC8                <1> 	dec	al
   362                              <1> 	;jz	L13
   363                              <1> 	; 02/01/2022
   364 00000149 7408                <1> 	jz	short L9_10
   365 0000014B 80FA80              <1> 	cmp	dl, 80h
   366                              <1>         ;jna	L5
   367                              <1> 	;jmp	L13
   368                              <1> 	; 02/01/2022
   369 0000014E 7703                <1> 	ja	short L9_10
   370 00000150 E972FF              <1> 	jmp	L5
   371                              <1> L9_10:
   372 00000153 E90501              <1>         jmp     L13
   373                              <1> L10:
   374 00000156 FEC2                <1> 	inc 	dl
   375                              <1> 	; 25/12/2014
   376 00000158 8816[595C]          <1> 	mov	[drv], dl
   377 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   378 0000015E CD13                <1> 	int	13h	; (conventional function)
   379                              <1> 	;jc	L13
   380                              <1> 	; 02/01/2022
   381 00000160 72F1                <1> 	jc	short L9_10
   382                              <1> 	; 14/01/2015
   383 00000162 8A16[595C]          <1> 	mov	dl, [drv]
   384 00000166 52                  <1> 	push	dx
   385 00000167 51                  <1> 	push	cx
   386 00000168 E8FE00              <1> 	call	set_disk_parms
   387 0000016B 59                  <1> 	pop	cx
   388 0000016C 5A                  <1> 	pop	dx
   389                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   390                              <1> 	; 04/02/2016 (esi -> si)
   391                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   392                              <1> 	;		 ; at the '_end' of kernel.
   393                              <1> 	;mov	word [si], 30
   394                              <1> 	; 06/07/2016
   395 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   396                              <1> 	; 09/07/2016
   397 00000170 B81E00              <1> 	mov	ax, 001Eh
   398 00000173 8824                <1> 	mov	[si], ah ; 0
   399 00000175 46                  <1> 	inc	si
   400 00000176 8904                <1> 	mov	word [si], ax
   401                              <1>  	; word [si] = 30
   402                              <1> 	;
   403 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   404 0000017A CD13                <1> 	int	13h
   405                              <1>         ;jc	L13
   406                              <1> 	; 02/01/2022
   407 0000017C 72D5                <1> 	jc	short L9_10
   408                              <1> 	; 04/02/2016 (ebx -> bx)
   409                              <1> 	; 14/01/2015
   410                              <1> 	;sub	bx, bx
   411 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   412 00000180 88D3                <1> 	mov	bl, dl
   413 00000182 80EB80              <1> 	sub	bl, 80h
   414 00000185 81C3[5E5C]          <1> 	add	bx, hd0_type
   415 00000189 8A07                <1> 	mov 	al, [bx]
   416 0000018B 0C80                <1> 	or	al, 80h
   417 0000018D 8807                <1> 	mov 	[bx], al	
   418 0000018F 81EB[5C5C]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   419 00000193 81C3[7E5C]          <1> 	add	bx, drv.status
   420 00000197 8807                <1> 	mov	[bx], al
   421                              <1> 	; 04/02/2016 (eax -> ax)
   422 00000199 8B4410              <1> 	mov	ax, [si+16]
   423 0000019C 854412              <1> 	test	ax, [si+18]
   424 0000019F 7413                <1> 	jz	short L10_A0h 
   425                              <1> 			; 'CHS only' disks on EDD system 
   426                              <1> 			;  are reported with ZERO disk size
   427 000001A1 81EB[7E5C]          <1> 	sub	bx, drv.status
   428 000001A5 C1E302              <1> 	shl	bx, 2
   429 000001A8 81C3[625C]          <1> 	add	bx, drv.size ; disk size (in sectors)
   430 000001AC 8907                <1> 	mov	[bx], ax
   431 000001AE 8B4412              <1> 	mov	ax, [si+18]
   432                              <1> 	;mov	[bx], ax
   433                              <1> 	; 02/01/2022 (BugFix)
   434 000001B1 894702              <1> 	mov	[bx+2], ax
   435                              <1> 
   436                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   437                              <1> 	 ; for CHS disks (28/02/2015)
   438                              <1> 	; 30/12/2014
   439 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   440 000001B7 88D0                <1> 	mov	al, dl
   441 000001B9 83E003              <1> 	and 	ax, 3
   442 000001BC C0E005              <1> 	shl	al, 5 ; *32
   443 000001BF 01C7                <1> 	add 	di, ax
   444 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   445 000001C4 8EC0                <1> 	mov	es, ax
   446                              <1> 	;
   447 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   448 000001C8 88CC                <1> 	mov	ah, cl	
   449 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   450 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   451 000001CE AB                  <1> 	stosw		
   452 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   453 000001D1 FEC0                <1> 	inc	al
   454 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   455 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   456 000001D6 AA                  <1> 	stosb
   457 000001D7 8A440C              <1> 	mov	al, [si+12]
   458 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   459 000001DB 31C0                <1>  	xor	ax, ax
   460                              <1> 	;dec	ax	 ; 02/01/2015 
   461 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   462                              <1> 	;xor	al, al	 ; 02/01/2015	
   463 000001DE AA                  <1> 	stosb		 ; reserved
   464 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   465                              <1> 		         ; (do not disable retries, 
   466                              <1> 			 ; more than 8 heads)
   467 000001E1 AA                  <1> 	stosb
   468 000001E2 8B4404              <1> 	mov	ax, [si+4]
   469 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   470                              <1> 	;push	ax	 ; 02/01/2015
   471 000001E6 8A4408              <1> 	mov	al, [si+8]
   472 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   473 000001EA 29C0                <1> 	sub 	ax, ax
   474                              <1> 	;pop	ax	 ; 02/01/2015	
   475 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   476 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   477 000001EF 243F                <1> 	and 	al, 3Fh	
   478 000001F1 AA                  <1> 	stosb
   479                              <1> 	;sub	al, al	 ; checksum
   480                              <1> 	;stosb
   481                              <1> 	;
   482 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   483 000001F5 AD                  <1> 	lodsw
   484 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   485 000001F7 AD                  <1> 	lodsw
   486 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   487                              <1> 	;
   488                              <1> 	; checksum calculation
   489 000001F9 89FE                <1> 	mov	si, di
   490 000001FB 06                  <1> 	push	es
   491 000001FC 1F                  <1> 	pop	ds
   492                              <1> 	;mov	cx, 16
   493 000001FD B90F00              <1> 	mov 	cx, 15
   494 00000200 29CE                <1> 	sub	si, cx
   495 00000202 30E4                <1> 	xor	ah, ah
   496                              <1> 	;del	cl
   497                              <1> L11:		
   498 00000204 AC                  <1> 	lodsb
   499 00000205 00C4                <1> 	add	ah, al
   500 00000207 E2FB                <1> 	loop	L11
   501                              <1> 	;
   502 00000209 88E0                <1> 	mov	al, ah
   503 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   504 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   505                              <1> 	;
   506 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   507 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   508                              <1> 	;
   509                              <1> 	; 23/02/2015
   510 00000210 57                  <1> 	push	di
   511                              <1> 	; ES:DI points to DPTE (FDPTE) location
   512                              <1> 	;mov	cx, 8
   513 00000211 B108                <1> 	mov	cl, 8
   514 00000213 F3A5                <1> 	rep	movsw	
   515                              <1> 	;
   516                              <1> 	; 23/02/2015
   517                              <1> 	; (P)ATA drive and LBA validation
   518                              <1> 	; (invalidating SATA drives and setting
   519                              <1> 	; CHS type I/O for old type fixed disks)
   520 00000215 5B                  <1> 	pop	bx
   521 00000216 8CC8                <1> 	mov	ax, cs
   522 00000218 8ED8                <1> 	mov	ds, ax
   523 0000021A 268B07              <1> 	mov	ax, [es:bx]
   524 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   525 00000220 7418                <1> 	je	short L11a
   526 00000222 3D7001              <1> 	cmp	ax, 170h
   527 00000225 7413                <1> 	je	short L11a
   528                              <1> 	; invalidation 
   529                              <1> 	; (because base port address is not 1F0h or 170h)
   530 00000227 30FF                <1> 	xor	bh, bh
   531 00000229 88D3                <1> 	mov	bl, dl
   532 0000022B 80EB80              <1> 	sub	bl, 80h
   533 0000022E C687[5E5C]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   534 00000233 808F[805C]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   535 00000238 EB14                <1> 	jmp	short L11b
   536                              <1> L11a:	
   537                              <1> 	; LBA validation
   538 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   539 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   540 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   541                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   542 00000242 28FF                <1> 	sub	bh, bh
   543 00000244 88D3                <1> 	mov	bl, dl
   544 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   545 00000249 80A7[805C]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   546                              <1> 				; bit 0 = LBA ready bit
   547                              <1> 	; 'diskio' procedure will check this bit !
   548                              <1> L11b:
   549 0000024E 3A16[5A5C]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   550 00000252 7307                <1>         jnb     short L13
   551 00000254 E9FFFE              <1>         jmp     L10
   552                              <1> L12:
   553                              <1> 	; Restore data registers
   554 00000257 8CC8                <1> 	mov	ax, cs
   555 00000259 8ED8                <1> 	mov	ds, ax	
   556                              <1> L13:
   557                              <1> 	; 13/12/2014
   558 0000025B 0E                  <1> 	push	cs
   559 0000025C 07                  <1> 	pop	es
   560                              <1> L14:
   561 0000025D B411                <1> 	mov 	ah, 11h
   562 0000025F CD16                <1> 	int 	16h
   563                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   564                              <1> 	; 02/01/2022
   565 00000261 7447                <1> 	jz	short L16
   566 00000263 B010                <1> 	mov	al, 10h
   567 00000265 CD16                <1> 	int 	16h
   568 00000267 EBF4                <1> 	jmp 	short L14
   569                              <1> L15:
   570                              <1> 
   571                              <1> ; //////
   572                              <1> 
   573                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   574                              <1> %if 0
   575                              <1> 	; 24/11/2014
   576                              <1> 	; 19/11/2014
   577                              <1> 	; 14/11/2014
   578                              <1> 	; Temporary code for disk searching code check
   579                              <1> 	;
   580                              <1> 	; This code will show existing (usable) drives and also
   581                              <1> 	; will show EDD interface support status for hard disks		
   582                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   583                              <1> 	; no need to get it again in protected mode...) 
   584                              <1> 	;	
   585                              <1> 	; 13/11/2014
   586                              <1> 	mov	bx, 7
   587                              <1> 	mov	ah, 0Eh
   588                              <1> 	mov	al, [fd0_type]
   589                              <1> 	and	al, al
   590                              <1> 	jz	short L15a
   591                              <1> 	mov	dl, al
   592                              <1> 	mov	al, 'F'
   593                              <1> 	int 	10h
   594                              <1> 	mov	al, 'D'
   595                              <1> 	int 	10h
   596                              <1> 	mov	al, '0'
   597                              <1> 	int 	10h
   598                              <1> 	mov	al, ' '
   599                              <1> 	int	10h
   600                              <1> 	call	L15c
   601                              <1> 	mov	al, ' '
   602                              <1> 	int	10h
   603                              <1> 	;
   604                              <1> 	mov	al, [fd1_type]
   605                              <1> 	and	al, al
   606                              <1> 	jz	short L15a
   607                              <1> 	mov	dl, al
   608                              <1> 	mov	al, 'F'
   609                              <1> 	int 	10h
   610                              <1> 	mov	al, 'D'
   611                              <1> 	int 	10h
   612                              <1> 	mov	al, '1'
   613                              <1> 	int 	10h
   614                              <1> 	mov	al, ' '
   615                              <1> 	int	10h
   616                              <1> 	call	L15c
   617                              <1> 	mov	al, ' '
   618                              <1> 	int	10h
   619                              <1> 	mov	al, ' '
   620                              <1> 	int	10h
   621                              <1> L15a:
   622                              <1> 	mov	al, [hd0_type]
   623                              <1> 	and	al, al
   624                              <1> 	jz	short L15b
   625                              <1> 	mov	dl, al
   626                              <1> 	mov	al, 'H'
   627                              <1> 	int 	10h
   628                              <1> 	mov	al, 'D'
   629                              <1> 	int 	10h
   630                              <1> 	mov	al, '0'
   631                              <1> 	int 	10h
   632                              <1> 	mov	al, ' '
   633                              <1> 	int 	10h
   634                              <1> 	call	L15c
   635                              <1> 	mov	al, ' '
   636                              <1> 	int	10h
   637                              <1> 	;
   638                              <1> 	mov	al, [hd1_type]
   639                              <1> 	and	al, al
   640                              <1> 	jz	short L15b
   641                              <1> 	mov	dl, al
   642                              <1> 	mov	al, 'H'
   643                              <1> 	int 	10h
   644                              <1> 	mov	al, 'D'
   645                              <1> 	int 	10h
   646                              <1> 	mov	al, '1'
   647                              <1> 	int 	10h
   648                              <1> 	mov	al, ' '
   649                              <1> 	int 	10h
   650                              <1> 	call	L15c
   651                              <1> 	mov	al, ' '
   652                              <1> 	int	10h
   653                              <1> 	;
   654                              <1> 	mov	al, [hd2_type]
   655                              <1> 	and	al, al
   656                              <1> 	jz	short L15b
   657                              <1> 	mov	dl, al
   658                              <1> 	mov	al, 'H'
   659                              <1> 	int 	10h
   660                              <1> 	mov	al, 'D'
   661                              <1> 	int 	10h
   662                              <1> 	mov	al, '2'
   663                              <1> 	int 	10h
   664                              <1> 	mov	al, ' '
   665                              <1> 	int 	10h
   666                              <1> 	call	L15c
   667                              <1> 	mov	al, ' '
   668                              <1> 	int	10h
   669                              <1> 	;
   670                              <1> 	mov	al, [hd3_type]
   671                              <1> 	and	al, al
   672                              <1> 	jz	short L15b
   673                              <1> 	mov	dl, al
   674                              <1> 	mov	al, 'H'
   675                              <1> 	int 	10h
   676                              <1> 	mov	al, 'D'
   677                              <1> 	int 	10h
   678                              <1> 	mov	al, '3'
   679                              <1> 	int 	10h
   680                              <1> 	mov	al, ' '
   681                              <1> 	int 	10h
   682                              <1> 	call	L15c
   683                              <1> 	mov	al, ' '
   684                              <1> 	int	10h
   685                              <1> 	;
   686                              <1> L15b:
   687                              <1> 	mov	al, 0Dh
   688                              <1> 	int 	10h	
   689                              <1> 	mov	al, 0Ah
   690                              <1> 	int 	10h
   691                              <1> 	;;xor	ah, ah
   692                              <1> 	;;int 	16h	
   693                              <1> 	;
   694                              <1>         ;jmp	L16  ; jmp short L16
   695                              <1>         ; 02/01/2022
   696                              <1> 	jmp	short L16
   697                              <1> 	;
   698                              <1> L15c:
   699                              <1> 	mov	dh, dl
   700                              <1> 	shr	dh, 4
   701                              <1> 	add	dh, 30h
   702                              <1> 	and	dl, 15
   703                              <1> 	add	dl, 30h
   704                              <1> 	mov	al, dh
   705                              <1> 	int	10h
   706                              <1> 	mov	al, dl
   707                              <1> 	int	10h
   708                              <1> 	retn
   709                              <1> 	;
   710                              <1> 	; end of temporary code for disk searching code check
   711                              <1> 
   712                              <1> %endif
   713                              <1> 
   714                              <1> ; //////
   715                              <1> 
   716                              <1> set_disk_parms:
   717                              <1> 	; 12/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
   718                              <1> 	; 09/05/2022
   719                              <1> 	;	disksize = cylinders*spt*heads (*)
   720                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders) 
   721                              <1> 	;
   722                              <1> 	; 04/02/2016 (ebx -> bx)
   723                              <1> 	; 10/07/2015
   724                              <1> 	; 14/01/2015
   725                              <1> 	;push	bx
   726 00000269 28FF                <1> 	sub	bh, bh
   727 0000026B 8A1E[595C]          <1> 	mov	bl, [drv]
   728 0000026F 80FB80              <1> 	cmp	bl, 80h
   729 00000272 7203                <1> 	jb	short sdp0
   730 00000274 80EB7E              <1> 	sub	bl, 7Eh
   731                              <1> sdp0:	
   732 00000277 81C3[7E5C]          <1> 	add	bx, drv.status
   733 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   734                              <1> 	;
   735 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   736 00000280 88CC                <1> 	mov	ah, cl ; 
   737 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   738 00000285 81EB[7E5C]          <1> 	sub	bx, drv.status
   739 00000289 D0E3                <1> 	shl	bl, 1
   740                              <1> 	; 12/07/2022
   741                              <1> 	;add	bx, drv.cylinders
   742 0000028B 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   743                              <1> 	;mov	[bx], ax
   744 0000028C 50                  <1> 	push	ax ; ** cylinders
   745                              <1> 	;sub	bx, drv.cylinders
   746                              <1> 	;add	bx, drv.heads
   747 0000028D 30E4                <1> 	xor	ah, ah
   748 0000028F 88F0                <1> 	mov	al, dh ; heads
   749 00000291 40                  <1> 	inc	ax
   750                              <1> 	;mov	[bx], ax
   751                              <1>         ;sub	bx, drv.heads
   752                              <1>         ;add	bx, drv.spt
   753 00000292 30ED                <1> 	xor	ch, ch
   754 00000294 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   755                              <1> 	;mov	[bx], cx
   756                              <1>         ;sub	bx, drv.spt
   757 00000297 D1E3                <1> 	shl	bx, 1
   758 00000299 81C3[625C]          <1> 	add	bx, drv.size ; disk size (in sectors)
   759                              <1> 	; LBA size = cylinders * heads * secpertrack
   760 0000029D F7E1                <1> 	mul	cx 
   761 0000029F 89C2                <1> 	mov	dx, ax	; heads*spt					
   762 000002A1 58                  <1> 	pop	ax ; ** cylinders
   763                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   764                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   765 000002A2 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   766 000002A4 8907                <1> 	mov	[bx], ax
   767 000002A6 895702              <1> 	mov	[bx+2], dx
   768                              <1> 	;
   769                              <1> 	;pop	bx
   770 000002A9 C3                  <1> 	retn
   771                              <1> 
   772                              <1> ;align 2
   773                              <1> 
   774                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   775                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   776                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   777                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   778                              <1> 
   779                              <1> ;last_drv:
   780                              <1> ;	db  0
   781                              <1> ;drv_status:
   782                              <1> ;	db  0,0,0,0,0,0
   783                              <1> ;	db 0
   784                              <1> 
   785                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   786                              <1> 
   787                              <1> L16:
   213                                  
   214                                  	; 10/11/2014
   215 000002AA FA                           	cli	; Disable interrupts (clear interrupt flag)
   216                                  		; Reset Interrupt MASK Registers (Master&Slave)
   217                                  	;mov	al, 0FFh	; mask off all interrupts
   218                                  	;out	21h, al		; on master PIC (8259)
   219                                  	;jmp 	$+2  ; (delay)
   220                                  	;out	0A1h, al	; on slave PIC (8259)
   221                                  	;
   222                                  	; Disable NMI 
   223 000002AB B080                    	mov   	al, 80h 
   224 000002AD E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   225                                  	; 23/02/2015
   226 000002AF 90                      	nop			;
   227                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   228                                  				; for preventing unknown state (!?)
   229                                  	;
   230                                   	; 20/08/2014
   231                                  	; Moving the kernel 64 KB back (to physical address 0)
   232                                  	; DS = CS = 1000h
   233                                  	; 05/11/2014
   234 000002B0 31C0                    	xor	ax, ax
   235 000002B2 8EC0                    	mov	es, ax ; ES = 0
   236                                  	;
   237 000002B4 B90040                  	mov	cx, (KEND - KLOAD)/4
   238 000002B7 31F6                    	xor	si, si
   239 000002B9 31FF                    	xor	di, di
   240 000002BB F366A5                  	rep	movsd
   241                                  	;
   242 000002BE 06                      	push	es ; 0
   243 000002BF 68[C302]                	push	L17
   244 000002C2 CB                      	retf
   245                                  	;
   246                                  L17:
   247                                  	; Turn off the floppy drive motor
   248 000002C3 BAF203                          mov     dx, 3F2h
   249 000002C6 EE                              out     dx, al ; 0 ; 31/12/2013
   250                                  
   251                                  	; Enable access to memory above one megabyte
   252                                  L18:
   253 000002C7 E464                    	in	al, 64h
   254 000002C9 A802                    	test	al, 2
   255 000002CB 75FA                            jnz     short L18
   256 000002CD B0D1                    	mov	al, 0D1h	; Write output port
   257 000002CF E664                    	out	64h, al
   258                                  L19:
   259 000002D1 E464                    	in	al, 64h
   260 000002D3 A802                    	test	al, 2
   261 000002D5 75FA                            jnz     short L19
   262 000002D7 B0DF                    	mov	al, 0DFh	; Enable A20 line
   263 000002D9 E660                    	out	60h, al
   264                                  ;L20:
   265                                  	;
   266                                  	; Load global descriptor table register
   267                                  
   268                                          ;mov     ax, cs
   269                                          ;mov     ds, ax
   270                                  
   271 000002DB 2E0F0116[8059]                  lgdt    [cs:gdtd]
   272                                  
   273 000002E1 0F20C0                          mov     eax, cr0
   274                                  	; or 	eax, 1
   275 000002E4 40                      	inc     ax
   276 000002E5 0F22C0                  	mov     cr0, eax
   277                                  
   278                                  	; Jump to 32 bit code
   279                                  	
   280 000002E8 66                      	db 66h 			; Prefix for 32-bit
   281 000002E9 EA                      	db 0EAh 		; Opcode for far jump
   282 000002EA [F0020000]              	dd StartPM 		; Offset to start, 32-bit
   283                                  				; (1000h:StartPM = StartPM + 10000h)
   284 000002EE 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   285                                  				; assuming that StartPM resides in code32
   286                                  
   287                                  [BITS 32] 
   288                                  
   289                                  StartPM:
   290                                  	; Kernel Base Address = 0 ; 30/12/2013
   291 000002F0 66B81000                	mov ax, KDATA           ; Save data segment identifier
   292 000002F4 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   293 000002F6 8EC0                           	mov es, ax              ; Move data segment into ES register
   294 000002F8 8EE0                           	mov fs, ax              ; Move data segment into FS register
   295 000002FA 8EE8                          	mov gs, ax              ; Move data segment into GS register
   296 000002FC 8ED0                            mov ss, ax              ; Move data segment into SS register
   297 000002FE BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   298                                  
   299                                  clear_bss: ; Clear uninitialized data area
   300                                  	; 11/03/2015
   301 00000303 31C0                    	xor	eax, eax ; 0
   302                                  	;mov	ecx, (bss_end - bss_start)/4
   303                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   304                                  	; 27/02/2022
   305 00000305 B9C0060000              	mov	ecx, BSS_SIZE/4
   306 0000030A BF[D05E0000]            	mov	edi, bss_start
   307 0000030F F3AB                    	rep	stosd  	
   308                                  
   309                                  memory_init:
   310                                  	; Initialize memory allocation table and page tables
   311                                  	; 16/11/2014
   312                                  	; 15/11/2014
   313                                  	; 07/11/2014
   314                                  	; 06/11/2014
   315                                  	; 05/11/2014
   316                                  	; 04/11/2014
   317                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   318                                  	;
   319                                  ;	xor	eax, eax
   320                                  ;	xor 	ecx, ecx
   321 00000311 B108                    	mov	cl, 8
   322 00000313 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   323 00000318 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   324                                  				   ; for the first 1 MB memory
   325                                  	;
   326 0000031A 668B0D[C25E0000]        	mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   327                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   328 00000321 66C1E902                	shr	cx, 2		   ; convert 1 KB count to 4 KB count
   329 00000325 890D[40610000]          	mov	[free_pages], ecx
   330 0000032B 668B15[C45E0000]        	mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   331                                  				   ; between 16 MB and 4 GB.	
   332 00000332 6609D2                  	or	dx, dx
   333 00000335 7413                    	jz	short mi_0
   334                                  	;
   335 00000337 6689D0                  	mov	ax, dx
   336 0000033A C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   337 0000033D 0105[40610000]          	add	[free_pages], eax
   338 00000343 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   339 00000348 EB07                    	jmp	short mi_1
   340                                  mi_0:
   341 0000034A 6689C8                  	mov	ax, cx
   342 0000034D 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB		 
   343                                  mi_1:
   344 00000351 A3[3C610000]            	mov	[memory_size], eax ; Total available memory in pages
   345                                  				   ; 1 alloc. tbl. bit = 1 memory page
   346                                  				   ; 32 allocation bits = 32 mem. pages   
   347                                  	;
   348 00000356 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page 	
   349 0000035B C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   350                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   351                                  				   ;  --> x M.A.T. pages, if y = 0
   352 0000035E 66A3[50610000]          	mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages		
   353 00000364 C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   354                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   355 00000367 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   356                                  	; Set/Calculate Kernel's Page Directory Address
   357 00000369 81C300001000            	add	ebx, MEM_ALLOC_TBL
   358 0000036F 891D[38610000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   359                                  				   ; just after the last M.A.T. page
   360                                  	;
   361 00000375 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   362 00000378 A3[48610000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   363                                  	;			   ; (allocation status search must be 
   364                                  				   ; stopped after here)	
   365 0000037D 31C0                    	xor	eax, eax
   366 0000037F 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)	
   367 00000380 6651                    	push	cx
   368 00000382 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to 
   369                                  				   ; count of 32 allocation bits
   370 00000385 F3AB                    	rep	stosd
   371 00000387 6659                    	pop	cx
   372 00000389 40                      	inc	eax		   ; 0	
   373 0000038A 80E11F                  	and	cl, 31		   ; remain bits
   374 0000038D 7412                    	jz	short mi_4
   375 0000038F 8907                    	mov	[edi], eax	   ; reset	
   376                                  mi_2:
   377 00000391 0FAB07                  	bts	[edi], eax	   ; 06/11/2014		
   378 00000394 FEC9                    	dec	cl
   379 00000396 7404                    	jz	short mi_3
   380 00000398 FEC0                    	inc	al
   381 0000039A EBF5                    	jmp	short mi_2
   382                                  mi_3:
   383 0000039C 28C0                    	sub	al, al	   	   ; 0
   384 0000039E 83C704                  	add	edi, 4		   ; 15/11/2014
   385                                  mi_4:
   386 000003A1 6609D2                  	or	dx, dx		  ; check 16M to 4G memory space	
   387 000003A4 7421                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   388                                  	;	
   389 000003A6 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   390                                  	;	
   391 000003AB 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   392 000003AD 7406                    	jz	short mi_5	  ; jump if EDI points to 
   393                                  				  ;         end of first 16 MB	
   394 000003AF D1E9                    	shr	ecx, 1		  ; convert to dword count
   395 000003B1 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   396 000003B3 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   397                                  				  ; (memory hole under 16 MB)
   398                                  mi_5:
   399 000003B5 6689D1                  	mov	cx, dx		  ; count of 64 KB memory blocks
   400 000003B8 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   401 000003BA 9C                      	pushf			  ; 16/11/2014		
   402 000003BB 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   403 000003BC F3AB                    	rep	stosd
   404 000003BE 40                      	inc	eax		  ; 0
   405 000003BF 9D                      	popf			  ; 16/11/2014
   406 000003C0 7305                    	jnc	short mi_6
   407 000003C2 6648                    	dec	ax		  ; eax = 0000FFFFh
   408 000003C4 AB                      	stosd
   409 000003C5 6640                    	inc	ax		  ; 0		
   410                                  mi_6:
   411 000003C7 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   412 000003C9 730A                    	jnb	short mi_7	  ; end of memory allocation table
   413                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   414 000003CB 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   415 000003CD 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   416 000003CF D1E9                    	shr	ecx, 1		  ; to dword count 	 		
   417 000003D1 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   418 000003D3 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   419                                  mi_7:
   420                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   421 000003D5 BA00001000              	mov	edx, MEM_ALLOC_TBL
   422                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   423                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   424 000003DA 668B0D[50610000]        	mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   425 000003E1 89D7                    	mov	edi, edx
   426 000003E3 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   427                                  				  ; byte offset in M.A.T.
   428                                  				  ; (1 M.A.T. byte points to 
   429                                  				  ;	      32768 bytes)
   430                                  				  ; Note: MEM_ALLOC_TBL address 
   431                                  				  ; must be aligned on 128 KB 
   432                                  				  ; boundary!
   433 000003E6 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   434                                  	; eax = 0
   435 000003E8 290D[40610000]          	sub	[free_pages], ecx ; 07/11/2014
   436                                  mi_8:
   437 000003EE 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   438                                  	;dec	bl
   439 000003F1 FEC9                    	dec	cl
   440 000003F3 7404                    	jz	short mi_9
   441 000003F5 FEC0                    	inc	al
   442 000003F7 EBF5                    	jmp	short mi_8
   443                                  mi_9:
   444                                  	;
   445                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   446                                  	;		(allocate pages for system page tables)
   447                                  
   448                                  	; edx = MEM_ALLOC_TBL
   449 000003F9 8B0D[3C610000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   450 000003FF 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)	 	
   451 00000405 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   452                                  				 ; page table count (PDE count)
   453                                  	;
   454 00000408 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   455                                  	;
   456 00000409 41                      	inc	ecx		 ; +1 for kernel page directory	
   457                                  	;
   458 0000040A 290D[40610000]          	sub	[free_pages], ecx ; 07/11/2014
   459                                  	;
   460 00000410 8B35[38610000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   461 00000416 C1EE0C                  	shr	esi, 12		 ; convert to page number
   462                                  mi_10:
   463 00000419 89F0                    	mov	eax, esi	 ; allocation bit offset		 
   464 0000041B 89C3                    	mov	ebx, eax
   465 0000041D C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   466 00000420 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   467                                  				 ;   to align on dword boundary
   468 00000423 83E01F                  	and	eax, 31		 ; set allocation bit position 
   469                                  				 ;  (bit 0 to bit 31)
   470                                  	;
   471 00000426 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   472                                  	;
   473 00000428 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   474                                  	;
   475 0000042B 46                      	inc	esi		 ; next page table
   476 0000042C E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   477                                  				 ; (ecx = page table count + 1)		
   478                                  	;
   479 0000042E 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   480                                  	;
   481                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   482                                  	;
   483                                  	; Initialize Kernel's Page Directory
   484 0000042F 8B3D[38610000]          	mov	edi, [k_page_dir]
   485 00000435 89F8                    	mov	eax, edi
   486 00000437 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   487                                  		     	      ; supervisor + read&write + present
   488 00000439 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)	
   489                                  mi_11:
   490 0000043B 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   491                                  			        ; EAX points to next page table
   492 00000440 AB                      	stosd
   493 00000441 E2F8                    	loop	mi_11
   494 00000443 29C0                    	sub	eax, eax	; Empty PDE
   495 00000445 66B90004                	mov	cx, 1024	; Entry count (PGSZ/4)
   496 00000449 29D1                    	sub	ecx, edx
   497 0000044B 7402                    	jz	short mi_12
   498 0000044D F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   499                                  	;
   500                                  	; Initialization of Kernel's Page Directory is OK, here.
   501                                  mi_12:
   502                                  	; Initialize Kernel's Page Tables
   503                                  	;
   504                                  	; (EDI points to address of page table 0)
   505                                  	; eax = 0
   506 0000044F 8B0D[3C610000]          	mov	ecx, [memory_size] ; memory size in pages
   507 00000455 89CA                    	mov	edx, ecx	; (***)
   508 00000457 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   509                                  			     ; supervisor + read&write + present 	
   510                                  mi_13:
   511 00000459 AB                      	stosd
   512 0000045A 0500100000              	add	eax, 4096	
   513 0000045F E2F8                    	loop	mi_13	
   514 00000461 6681E2FF03              	and	dx, 1023	; (***)
   515 00000466 740B                    	jz	short mi_14
   516 00000468 66B90004                	mov	cx, 1024	
   517 0000046C 6629D1                  	sub	cx, dx		; from dx (<= 1023) to 1024
   518 0000046F 31C0                    	xor	eax, eax
   519 00000471 F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   520                                  				; of the last page table
   521                                  mi_14:
   522                                  	;  Initialization of Kernel's Page Tables is OK, here.
   523                                  	;
   524 00000473 89F8                    	mov	eax, edi	; end of the last page table page
   525                                  			        ; (beginging of user space pages)
   526 00000475 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   527 00000478 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   528                                  				; aligning on dword boundary	
   529                                  	 
   530 0000047A A3[4C610000]            	mov	[first_page], eax
   531 0000047F A3[44610000]            	mov	[next_page], eax ; The first free page pointer
   532                                  				 ; for user programs
   533                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   534                                  	;
   535                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   536                                  	;
   537                                  	
   538                                  	; Enable paging
   539                                  	;
   540 00000484 A1[38610000]                    mov     eax, [k_page_dir]
   541 00000489 0F22D8                  	mov	cr3, eax
   542 0000048C 0F20C0                  	mov	eax, cr0
   543 0000048F 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   544 00000494 0F22C0                  	mov	cr0, eax
   545                                          ;jmp    KCODE:StartPMP
   546                                  
   547 00000497 EA                      	db 0EAh 		; Opcode for far jump
   548 00000498 [9E040000]                      dd StartPMP		; 32 bit offset
   549 0000049C 0800                    	dw KCODE		; kernel code segment descriptor
   550                                  
   551                                  
   552                                  StartPMP:
   553                                  	; 06/11//2014
   554                                  	; Clear video page 0
   555                                  	;
   556                                  	; Temporary Code
   557                                  	;
   558 0000049E B9E8030000              	mov	ecx, 80*25/2
   559 000004A3 BF00800B00              	mov	edi, 0B8000h
   560 000004A8 31C0                    	xor	eax, eax	; black background, black fore color
   561 000004AA F3AB                    	rep	stosd
   562                                  	
   563                                  	; 19/08/2014
   564                                  	; Kernel Base Address = 0
   565                                  	; It is mapped to (physically) 0 in the page table.
   566                                  	; So, here is exactly 'StartPMP' address.
   567                                  	;
   568                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   569                                  	;;mov	esi, msgPM
   570                                  	;; 14/08/2015 (kernel version message will appear
   571                                  	;;	       when protected mode and paging is enabled)
   572 000004AC B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   573 000004AE BE[945C0000]            	mov	esi, msgKVER
   574 000004B3 BF00800B00              	mov	edi, 0B8000h ; 27/08/2014
   575                                  	; 20/08/2014
   576 000004B8 E891010000              	call	printk
   577                                  
   578                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   579                                  	; // Set IRQ offsets
   580                                  	;
   581                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   582                                  	;
   583                                  					;; ICW1
   584 000004BD B011                    	mov	al, 11h			; Initialization sequence
   585 000004BF E620                    	out	20h, al			; 	8259A-1
   586                                  	; jmp 	$+2
   587 000004C1 E6A0                    	out	0A0h, al		; 	8259A-2
   588                                  					;; ICW2
   589 000004C3 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   590 000004C5 E621                    	out	21h, al			;	for 8259A-1
   591                                  	; jmp 	$+2
   592 000004C7 B028                    	mov	al, 28h			; Start of hardware ints (28h)
   593 000004C9 E6A1                    	out	0A1h, al		; 	for 8259A-2
   594                                  					;
   595 000004CB B004                    	mov	al, 04h			;; ICW3
   596 000004CD E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   597                                  	; jmp 	$+2
   598 000004CF B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   599 000004D1 E6A1                    	out	0A1h, al		;
   600                                  					;; ICW4
   601 000004D3 B001                    	mov	al, 01h	 		;
   602 000004D5 E621                    	out	21h, al			; 	8086 mode, normal EOI	
   603                                  	; jmp 	$+2
   604 000004D7 E6A1                    	out	0A1h, al		;	for both chips.
   605                                  
   606                                  	;mov	al, 0FFh	; mask off all interrupts for now
   607                                  	;out	21h, al
   608                                  	;; jmp 	$+2
   609                                  	;out	0A1h, al
   610                                  
   611                                  	; 02/04/2015
   612                                  	; 26/03/2015 System call (INT 30h) modification
   613                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   614                                  	;
   615                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   616                                  	;  setup_idt:
   617                                  	;
   618                                          ;; 16/02/2015
   619                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   620                                  	; 21/08/2014 (timer_int)
   621 000004D9 BE[8C590000]            	mov	esi, ilist
   622 000004DE 8D3D[D05E0000]          	lea	edi, [idt]
   623                                  	; 26/03/2015
   624 000004E4 B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   625                                  	; 02/04/2015
   626 000004E9 BB00000800              	mov	ebx, 80000h
   627                                  rp_sidt1:
   628 000004EE AD                      	lodsd
   629 000004EF 89C2                    	mov	edx, eax
   630 000004F1 66BA008E                	mov	dx, 8E00h
   631 000004F5 6689C3                  	mov	bx, ax
   632 000004F8 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   633                                         			        ; /* interrupt gate - dpl=0, present */
   634 000004FA AB                      	stosd	; selector & offset bits 0-15 	
   635 000004FB 89D0                    	mov	eax, edx
   636 000004FD AB                      	stosd	; attributes & offset bits 16-23
   637 000004FE E2EE                    	loop	rp_sidt1
   638 00000500 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   639                                  rp_sidt2:
   640 00000502 AD                      	lodsd
   641 00000503 21C0                    	and	eax, eax
   642 00000505 7413                    	jz	short rp_sidt3
   643 00000507 89C2                    	mov	edx, eax
   644 00000509 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   645 0000050D 6689C3                  	mov	bx, ax
   646 00000510 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   647 00000512 AB                      	stosd
   648 00000513 89D0                    	mov	eax, edx
   649 00000515 AB                      	stosd
   650 00000516 E2EA                    	loop	rp_sidt2
   651 00000518 EB16                    	jmp	short sidt_OK
   652                                  rp_sidt3:
   653 0000051A B8[71090000]            	mov	eax, ignore_int
   654 0000051F 89C2                    	mov	edx, eax
   655 00000521 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   656 00000525 6689C3                  	mov	bx, ax
   657 00000528 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   658                                  rp_sidt4:
   659 0000052A AB                      	stosd
   660 0000052B 92                      	xchg	eax, edx
   661 0000052C AB                      	stosd
   662 0000052D 92                      	xchg	edx, eax
   663 0000052E E2FA                    	loop	rp_sidt4
   664                                  sidt_OK: 
   665 00000530 0F011D[86590000]        	lidt 	[idtd]
   666                                  	;
   667                                  	; TSS descriptor setup ; 24/03/2015
   668 00000537 B8[D0600000]            	mov	eax, task_state_segment
   669 0000053C 66A3[7A590000]          	mov	[gdt_tss0], ax
   670 00000542 C1C010                  	rol	eax, 16
   671 00000545 A2[7C590000]            	mov	[gdt_tss1], al
   672 0000054A 8825[7F590000]          	mov	[gdt_tss2], ah
   673 00000550 66C705[36610000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   673 00000558 00                 
   674                                  		; 
   675                                  		; IO Map Base address (When this address points
   676                                  		; to end of the TSS, CPU does not use IO port 
   677                                  		; permission bit map for RING 3 IO permissions, 
   678                                  		; access to any IO ports in ring 3 will be forbidden.)
   679                                   		;
   680                                  	;mov	[tss.esp0], esp ; TSS offset 4
   681                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   682 00000559 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   683                                  			 ; occurs (or a system call -software INT- is requested)
   684                                  			 ; while cpu running in ring 3 (in user mode).				
   685                                  			 ; (Kernel stack pointer and segment will be loaded
   686                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   687 0000055D 0F00D8                  	ltr	ax  ; Load task register
   688                                  	;
   689                                  esp0_set0:
   690                                  	; 30/07/2015
   691 00000560 8B0D[3C610000]          	mov 	ecx, [memory_size] ; memory size in pages
   692 00000566 C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   693 00000569 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   694                                  			  ; (kernel mode virtual address)
   695 0000056F 7605                    	jna	short esp0_set1
   696                                  	;
   697                                  	; If available memory > CORE (end of the 1st 4 MB)
   698                                  	; set stack pointer to CORE
   699                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   700                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   701 00000571 B900004000              	mov	ecx, CORE
   702                                  esp0_set1:
   703 00000576 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   704                                  esp0_set_ok:
   705                                  	; 30/07/2015 (**tss.esp0**) 
   706 00000578 8925[D4600000]          	mov	[tss.esp0], esp
   707 0000057E 66C705[D8600000]10-             mov     word [tss.ss0], KDATA
   707 00000586 00                 
   708                                  	; 14/08/2015
   709                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   710                                  	;
   711                                  	;cli	; Disable interrupts (for CPU)
   712                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   713                                  	;
   714 00000587 30C0                    	xor	al, al		; Enable all hardware interrupts!
   715 00000589 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   716 0000058B EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   717 0000058D E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   718                                  				; (Even if related hardware component
   719                                  				;  does not exist!)
   720                                  	; Enable NMI 
   721 0000058F B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   722 00000591 E670                    	out  	70h, al
   723                                  	; 23/02/2015
   724 00000593 90                      	nop
   725 00000594 E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   726                                  				; for preventing unknown state (!?)
   727                                  	;
   728                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   729                                  	;
   730                                  	; 02/09/2014
   731                                  	;xor	bx, bx
   732                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   733                                  	; 27/02/2022	
   734 00000596 31DB                    	xor	ebx, ebx
   735 00000598 31D2                    	xor	edx, edx
   736 0000059A B602                    	mov	dh, 2
   737 0000059C E81E0E0000              	call	set_cpos
   738                                  	;
   739                                  	; 06/11/2014
   740                                  	; Temporary Code
   741                                  	;
   742 000005A1 E8930F0000              	call	memory_info
   743                                  	; 14/08/2015
   744                                  	;call getch ; 28/02/2015
   745                                  drv_init:
   746 000005A6 FB                      	sti	; Enable Interrupts 
   747                                  	; 06/02/2015
   748 000005A7 8B15[5E5C0000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   749 000005AD 668B1D[5C5C0000]        	mov	bx, [fd0_type] ; fd0, fd1
   750                                  	; 22/02/2015
   751 000005B4 6621DB                  	and	bx, bx
   752 000005B7 751B                    	jnz	short di1
   753                                  	;
   754 000005B9 09D2                    	or 	edx, edx
   755 000005BB 7529                    	jnz	short di2
   756                                  	;
   757                                  setup_error:
   758 000005BD BE[7B5D0000]            	mov 	esi, setup_error_msg
   759                                  psem:	
   760 000005C2 AC                      	lodsb
   761 000005C3 08C0                    	or	al, al
   762                                  	;jz	short haltx ; 22/02/2015
   763 000005C5 7426                    	jz	short di3
   764 000005C7 56                      	push	esi
   765 000005C8 31DB                    	xor	ebx, ebx ; 0
   766                                  			; Video page 0 (bl=0)
   767 000005CA B407                    	mov	ah, 07h ; Black background, 
   768                                  			; light gray forecolor
   769 000005CC E8E40C0000              	call	write_tty
   770 000005D1 5E                      	pop	esi
   771 000005D2 EBEE                    	jmp	short psem
   772                                  
   773                                  di1:
   774                                  	; supress 'jmp short T6'
   775                                  	;  (activate fdc motor control code)
   776 000005D4 66C705[CF060000]90-     	mov	word [T5], 9090h ; nop
   776 000005DC 90                 
   777                                  	;
   778                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   779                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   780                                  	;stosw
   781                                  	;mov 	ax, cs
   782                                  	;stosw
   783                                  	;; 16/02/2015
   784                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   785                                  	;
   786 000005DD E804190000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   787                                  	;
   788 000005E2 09D2                    	or	edx, edx
   789 000005E4 7407                            jz      short di3
   790                                  di2:
   791 000005E6 E82D190000              	call   	DISK_SETUP	; Initialize Fixed Disks
   792 000005EB 72D0                            jc      short setup_error
   793                                  di3:
   794 000005ED E81B0F0000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   795                                  	;
   796 000005F2 E8B1520000              	call	display_disks ; 07/03/2015  (Temporary)
   797                                  ;haltx:
   798                                  	; 14/08/2015
   799                                  	;call	getch ; 22/02/2015
   800 000005F7 FB                      	sti	; Enable interrupts (for CPU)
   801                                  	; 14/08/2015
   802                                  	;mov 	ecx, 0FFFFFFFh
   803                                  	; 16/02/2022
   804 000005F8 B9FFFF4F00              	mov 	ecx, 04FFFFFh
   805                                  md_info_msg_wait:
   806 000005FD 51                      	push 	ecx
   807 000005FE B001                    	mov	al, 1
   808 00000600 8A25[66610000]          	mov 	ah, [ptty] ; active (current) video page
   809 00000606 E8884F0000              	call	getc_n
   810 0000060B 59                      	pop	ecx
   811 0000060C 7502                    	jnz	short md_info_msg_ok
   812 0000060E E2ED                    	loop	md_info_msg_wait
   813                                  md_info_msg_ok:
   814                                  	; 30/06/2015
   815 00000610 E8C1220000              	call	sys_init
   816                                  	;
   817                                  	;jmp 	cpu_reset ; 22/02/2015
   818                                  hang:
   819                                  	; 27/02/2022
   820 00000615 29C0                    	sub	eax, eax
   821                                  _hang: 
   822                                  	; 23/02/2015
   823                                  	;sti			; Enable interrupts
   824 00000617 F4                      	hlt
   825                                  	;
   826                                  	;nop
   827                                  	;; 03/12/2014
   828                                  	;; 28/08/2014
   829                                  	;mov	ah, 11h
   830                                  	;call	getc
   831                                  	;jz      _c8
   832                                  	;
   833                                  	; 23/02/2015
   834                                  	; 06/02/2015
   835                                  	; 07/09/2014
   836 00000618 31DB                    	xor	ebx, ebx
   837 0000061A 8A1D[66610000]          	mov	bl, [ptty]	; active_page
   838 00000620 89DE                    	mov	esi, ebx
   839                                  	;shl 	si, 1
   840                                  	; 17/07/2022
   841 00000622 D1E6                    	shl	esi, 1
   842 00000624 81C6[68610000]          	add	esi, ttychr
   843 0000062A 668B06                  	mov	ax, [esi]
   844                                  	;and	ax, ax
   845                                  	;;jz	short _c8
   846                                  	;jz	short hang
   847                                  	; 27/02/2022
   848 0000062D 21C0                    	and	eax, eax
   849 0000062F 74E6                    	jz	short _hang
   850 00000631 66C7060000              	mov	word [esi], 0
   851 00000636 80FB03                  	cmp	bl, 3		; Video page 3
   852                                  	;jb	short _c8
   853 00000639 72DA                    	jb	short hang
   854                                  	;	
   855                                  	; 02/09/2014
   856 0000063B B40E                    	mov	ah, 0Eh		; Yellow character 
   857                                  				; on black background
   858                                  	; 27/02/2022 (32 bit reg push-pop)
   859                                  	; 07/09/2014
   860                                  nxtl:
   861                                  	;push	bx
   862 0000063D 53                      	push	ebx
   863                                  	;
   864                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   865                                  				; bh = 0 (video mode)
   866                                  				; Retro UNIX 386 v1 - Video Mode 0
   867                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   868 0000063E 50                      	push	eax
   869 0000063F E8710C0000              	call 	write_tty
   870 00000644 58                      	pop	eax
   871                                  	;pop	bx
   872 00000645 5B                      	pop	ebx
   873 00000646 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   874                                  	;jne	short _c8
   875 00000648 75CB                    	jne	short hang
   876 0000064A B00A                    	mov	al, 0Ah		; next line
   877 0000064C EBEF                    	jmp	short nxtl
   878                                  	
   879                                  ;_c8:
   880                                  ;	; 25/08/2014
   881                                  ;	cli				; Disable interrupts
   882                                  ;	mov	al, [scounter + 1]
   883                                  ;	and	al, al
   884                                  ;	jnz	hang
   885                                  ;	call	rtc_p
   886                                  ;	jmp     hang
   887                                  
   888                                  
   889                                  	; 27/08/2014
   890                                  	; 20/08/2014
   891                                  printk:
   892                                          ;mov    edi, [scr_row]
   893                                  pkl:
   894 0000064E AC                      	lodsb
   895 0000064F 08C0                    	or 	al, al
   896 00000651 7404                    	jz	short pkr
   897 00000653 66AB                    	stosw
   898 00000655 EBF7                    	jmp	short pkl
   899                                  pkr:
   900 00000657 C3                      	retn
   901                                  
   902                                  ; 25/07/2015
   903                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   904                                  ; 17/02/2015
   905                                  ; 06/02/2015 (unix386.s)
   906                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   907                                  ;
   908                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   909                                  ;
   910                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   911                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   912                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   913                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   914                                  ;									       :
   915                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   916                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   917                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   918                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   919                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   920                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   921                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   922                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   923                                  ;-------------------------------------------------------------------------------
   924                                  ;
   925                                  
   926                                  timer_int:	; IRQ 0
   927                                  ;int_08h:	; Timer
   928                                  	; 14/10/2015
   929                                  	; Here, we are simulating system call entry (for task switch)
   930                                  	; (If multitasking is enabled, 
   931                                  	; 'clock' procedure may jump to 'sysrelease')
   932 00000658 1E                      	push	ds
   933 00000659 06                      	push	es
   934 0000065A 0FA0                    	push	fs
   935 0000065C 0FA8                    	push	gs
   936 0000065E 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   937 0000065F 66B91000                	mov     cx, KDATA
   938 00000663 8ED9                            mov     ds, cx
   939 00000665 8EC1                            mov     es, cx
   940 00000667 8EE1                            mov     fs, cx
   941 00000669 8EE9                            mov     gs, cx
   942                                  	;
   943 0000066B 0F20D9                  	mov	ecx, cr3
   944 0000066E 890D[11070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   945                                  	;
   946 00000674 3B0D[38610000]          	cmp 	ecx, [k_page_dir]
   947 0000067A 741F                    	je	short T3
   948                                  	;
   949                                  	; timer interrupt has been occurred while OS is in user mode
   950 0000067C A3[00650000]            	mov 	[u.r0], eax
   951 00000681 89E1                    	mov	ecx, esp
   952 00000683 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   953 00000686 890D[F8640000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   954 0000068C 8925[FC640000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   955                                  	;
   956 00000692 8B0D[38610000]          	mov	ecx, [k_page_dir]
   957 00000698 0F22D9                  	mov	cr3, ecx
   958                                  T3:
   959 0000069B FB                      	sti				; INTERRUPTS BACK ON
   960 0000069C 66FF05[B4610000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   961 000006A3 7507                    	JNZ	short T4		; GO TO TEST_DAY
   962 000006A5 66FF05[B6610000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   963                                  T4:					; TEST_DAY
   964 000006AC 66833D[B6610000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   965 000006B4 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   966 000006B6 66813D[B4610000]B0-     	CMP	word [TIMER_LOW],0B0H
   966 000006BE 00                 
   967 000006BF 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   968                                  
   969                                  ;-----	TIMER HAS GONE 24 HOURS
   970                                  	;;SUB	AX,AX
   971                                  	;MOV	[TIMER_HIGH],AX
   972                                  	;MOV	[TIMER_LOW],AX
   973 000006C1 29C0                    	sub	eax, eax
   974 000006C3 A3[B4610000]            	mov	[TIMER_LH], eax
   975                                  	;	
   976 000006C8 C605[B8610000]01        	MOV	byte [TIMER_OFL],1
   977                                  
   978                                  ;-----	TEST FOR DISKETTE TIME OUT
   979                                  
   980                                  T5:
   981                                  	; 23/12/2014
   982 000006CF EB1D                    	jmp	short T6		; will be replaced with nop, nop
   983                                  					; (9090h) if a floppy disk
   984                                  					; is detected.
   985                                  	;mov	al,[CS:MOTOR_COUNT]
   986 000006D1 A0[BB610000]            	mov	al, [MOTOR_COUNT]
   987 000006D6 FEC8                    	dec	al
   988                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
   989 000006D8 A2[BB610000]            	mov	[MOTOR_COUNT], al
   990                                  	;mov	[ORG_MOTOR_COUNT], al
   991 000006DD 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
   992 000006DF B0F0                    	mov 	al,0F0h
   993                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
   994 000006E1 2005[BA610000]          	and	[MOTOR_STATUS], al
   995                                  	;and	[ORG_MOTOR_STATUS], al
   996 000006E7 B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
   997                                  					; bit 2 = enable controller
   998                                  					;	1 = normal operation
   999                                  					;	0 = reset	
  1000                                  					; bit 0, 1 = drive select
  1001                                  					; bit 4-7 = motor running bits 
  1002 000006E9 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1003 000006ED EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1004                                  T6:	
  1005                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1006                                  					; TIMER TICK INTERRUPT
  1007                                  	;;inc	word [wait_count] ;;27/02/2015
  1008                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1009                                  	;;;;cli
  1010                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1011 000006EE FF15[09070000]          	call	[x_timer] ; 14/05/2015
  1012                                  T7:
  1013                                  	; 14/10/2015
  1014 000006F4 B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1015 000006F6 FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1016 000006F7 E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1017                                  	;
  1018 000006F9 A1[11070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1019 000006FE 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1020                                  	;
  1021 00000701 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1022                                  	;
  1023 00000702 0FA9                    	pop	gs
  1024 00000704 0FA1                    	pop	fs
  1025 00000706 07                      	pop	es
  1026 00000707 1F                      	pop	ds
  1027 00000708 CF                      	iretd	; return from interrupt
  1028                                  
  1029                                  
  1030                                  ; ////////////////
  1031                                  
  1032                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1033                                  x_timer:
  1034 00000709 [15070000]              	dd 	u_timer	; (temporary demo code)	; 14/05/2015
  1035                                  	;dd	clock
  1036                                  
  1037                                  ; 23/02/2022 - Real time clock (digital) output demo (sys emt)
  1038                                  x_rtci:
  1039 0000070D [4A0A0000]              	dd	rtc_p	; (temporary demo code)	; 23/02/2022
  1040                                  
  1041                                  ; 14/10/2015
  1042 00000711 00000000                cr3reg: dd 0
  1043                                  
  1044                                  	; 06/02/2015
  1045                                  	; 07/09/2014
  1046                                  	; 21/08/2014
  1047                                  u_timer:
  1048                                  	; 27/02/2022
  1049                                  	; 12/02/2022
  1050                                  ;timer_int:	; IRQ 0
  1051                                  	; 06/02/2015
  1052                                  	;push	eax
  1053                                  	;push	edx
  1054                                  	;push	ecx
  1055                                  	;push	ebx
  1056                                  	;push	ds
  1057                                  	;push	es
  1058                                  	;mov	eax, KDATA
  1059                                  	;mov	ds, ax
  1060                                  	;mov	es, ax
  1061 00000715 FF05[7C610000]          	inc	dword [tcount]
  1062 0000071B BB[045D0000]            	mov	ebx, tcountstr + 4
  1063                                  	;mov	ax, [tcount]
  1064                                  	; 27/02/2022
  1065 00000720 A1[7C610000]            	mov	eax, [tcount]
  1066                                  	;mov	ecx, 10
  1067 00000725 31C9                    	xor	ecx, ecx
  1068 00000727 B10A                    	mov	cl, 10
  1069                                  rp_divtcnt:
  1070 00000729 31D2                    	xor	edx, edx
  1071 0000072B F7F1                    	div	ecx
  1072 0000072D 80C230                  	add	dl, 30h
  1073 00000730 8813                    	mov	[ebx], dl
  1074                                  	;or	ax, ax
  1075                                  	; 27/02/2022
  1076 00000732 09C0                    	or	eax, eax
  1077 00000734 7403                    	jz	short print_lzero
  1078 00000736 4B                      	dec	ebx
  1079 00000737 EBF0                    	jmp	short rp_divtcnt
  1080                                  print_lzero:
  1081 00000739 81FB[005D0000]          	cmp	ebx, tcountstr
  1082 0000073F 7606                    	jna	short print_tcount
  1083 00000741 4B                      	dec	ebx
  1084 00000742 C60330                   	mov	byte [ebx], 30h
  1085 00000745 EBF2                    	jmp	short print_lzero
  1086                                  print_tcount:
  1087 00000747 56                      	push	esi
  1088 00000748 57                      	push	edi
  1089 00000749 BE[DC5C0000]            	mov	esi, timer_msg ; Timer interrupt message
  1090                                  	;; 07/09/2014
  1091                                  	;mov	bx, 1		; Video page 1
  1092                                  	; 12/02/2022
  1093                                  	;mov	bx, 6		; Video page 6
  1094                                  	; 27/02/2022
  1095 0000074E 29DB                    	sub	ebx, ebx
  1096 00000750 B306                    	mov	bl, 6	; Video page 6
  1097                                  ptmsg:
  1098 00000752 AC                      	lodsb
  1099 00000753 08C0                    	or	al, al
  1100 00000755 740D                    	jz	short ptmsg_ok
  1101 00000757 56                      	push	esi
  1102                                  	;push	bx
  1103                                  	; 27/02/2022
  1104 00000758 53                              push	ebx
  1105 00000759 B42F                            mov     ah,  2Fh ; Green background, white forecolor
  1106 0000075B E8550B0000              	call 	write_tty
  1107                                  	;pop	bx
  1108                                  	; 27/02/2022
  1109 00000760 5B                      	pop	ebx
  1110 00000761 5E                      	pop	esi
  1111 00000762 EBEE                    	jmp	short ptmsg
  1112                                  	;; 27/08/2014
  1113                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1114                                  	;call	printk
  1115                                  	;
  1116                                  ptmsg_ok:
  1117                                  	; 07/09/2014
  1118                                  	;xor	dx, dx		; column 0, row 0
  1119                                  	; 27/02/2022
  1120 00000764 31D2                    	xor	edx, edx
  1121 00000766 E8540C0000              	call	set_cpos	; set cursor position to 0,0 
  1122                                  	; 23/02/2015
  1123                                  	; 25/08/2014
  1124                                  	;mov	ebx, scounter		; (seconds counter)
  1125                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1126                                  ;	dec	byte [scounter+1]
  1127                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1128                                  ;	jns	short u_timer_retn
  1129                                  	; 26/02/2015
  1130                                  ;	call	rtc_p
  1131                                  ;	mov	ebx, scounter		; (seconds counter)
  1132                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1133                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1134                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1135                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1136                                  ;	mov	byte [ebx], 5
  1137                                  ;	inc	byte [ebx+1] ; 19
  1138                                  ;;timer_eoi:
  1139                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1140                                  ;;	out	20h, al	; 8259 PORT
  1141                                  	;
  1142                                  ;u_timer_retn:  ; 06/02/2015
  1143 0000076B 5F                      	pop	edi
  1144 0000076C 5E                      	pop	esi
  1145                                  	;pop	es
  1146                                  	;pop	ds
  1147                                  	;pop	ebx
  1148                                  	;pop	ecx
  1149                                  	;pop	edx
  1150                                  	;pop	eax
  1151                                  	;iret
  1152 0000076D C3                      	retn	; 06/02/2015
  1153                                  
  1154                                  	; 28/08/2014
  1155                                  irq0:
  1156 0000076E 6A00                            push 	dword 0
  1157 00000770 EB48                    	jmp	short which_irq
  1158                                  irq1:
  1159 00000772 6A01                            push 	dword 1
  1160 00000774 EB44                    	jmp	short which_irq
  1161                                  irq2:
  1162 00000776 6A02                            push 	dword 2
  1163 00000778 EB40                    	jmp	short which_irq
  1164                                  irq3:
  1165                                  	; 20/11/2015
  1166                                  	; 24/10/2015
  1167 0000077A 2EFF15[E42F0000]        	call	dword [cs:com2_irq3]
  1168 00000781 6A03                    	push 	dword 3
  1169 00000783 EB35                    	jmp	short which_irq
  1170                                  irq4:
  1171                                  	; 20/11/2015
  1172                                  	; 24/10/2015
  1173 00000785 2EFF15[E02F0000]        	call	dword [cs:com1_irq4]
  1174 0000078C 6A04                            push 	dword 4
  1175 0000078E EB2A                    	jmp	short which_irq
  1176                                  irq5:
  1177 00000790 6A05                            push 	dword 5
  1178 00000792 EB26                    	jmp	short which_irq
  1179                                  irq6:
  1180 00000794 6A06                            push 	dword 6
  1181 00000796 EB22                    	jmp	short which_irq
  1182                                  irq7:
  1183 00000798 6A07                            push 	dword 7
  1184 0000079A EB1E                    	jmp	short which_irq
  1185                                  irq8:
  1186 0000079C 6A08                            push 	dword 8
  1187 0000079E EB1A                    	jmp	short which_irq
  1188                                  irq9:
  1189 000007A0 6A09                            push 	dword 9
  1190 000007A2 EB16                    	jmp	short which_irq
  1191                                  irq10:
  1192 000007A4 6A0A                            push 	dword 10
  1193 000007A6 EB12                    	jmp	short which_irq
  1194                                  irq11:
  1195 000007A8 6A0B                            push 	dword 11
  1196 000007AA EB0E                    	jmp	short which_irq
  1197                                  irq12:
  1198 000007AC 6A0C                            push 	dword 12
  1199 000007AE EB0A                    	jmp	short which_irq
  1200                                  irq13:
  1201 000007B0 6A0D                            push 	dword 13
  1202 000007B2 EB06                    	jmp	short which_irq
  1203                                  irq14:
  1204 000007B4 6A0E                            push 	dword 14
  1205 000007B6 EB02                    	jmp	short which_irq
  1206                                  irq15:
  1207 000007B8 6A0F                            push 	dword 15
  1208                                  	;jmp	short which_irq
  1209                                  
  1210                                  	; 27/02/2022
  1211                                  	; 19/10/2015
  1212                                  	; 29/08/2014
  1213                                  	; 21/08/2014
  1214                                  which_irq:
  1215 000007BA 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1216 000007BD 53                      	push	ebx
  1217 000007BE 56                      	push	esi
  1218 000007BF 57                      	push	edi
  1219 000007C0 1E                      	push 	ds
  1220 000007C1 06                      	push 	es
  1221                                  	;
  1222 000007C2 88C3                    	mov	bl, al
  1223                                  	;
  1224 000007C4 B810000000              	mov	eax, KDATA
  1225 000007C9 8ED8                    	mov	ds, ax
  1226 000007CB 8EC0                    	mov	es, ax
  1227                                  	; 19/10/2015
  1228 000007CD FC                      	cld
  1229                                          ; 27/08/2014
  1230 000007CE 8105[8C5C0000]A000-             add     dword [scr_row], 0A0h
  1230 000007D6 0000               
  1231                                  	;
  1232 000007D8 B417                    	mov	ah, 17h	; blue (1) background, 
  1233                                  			; light gray (7) forecolor
  1234 000007DA 8B3D[8C5C0000]                  mov     edi, [scr_row]
  1235 000007E0 B049                    	mov	al, 'I'
  1236 000007E2 66AB                    	stosw
  1237 000007E4 B052                    	mov	al, 'R'
  1238 000007E6 66AB                    	stosw
  1239 000007E8 B051                    	mov	al, 'Q'
  1240 000007EA 66AB                    	stosw
  1241 000007EC B020                    	mov	al, ' '
  1242 000007EE 66AB                    	stosw
  1243 000007F0 88D8                    	mov	al, bl
  1244 000007F2 3C0A                    	cmp	al, 10
  1245 000007F4 7208                    	jb	short iix
  1246 000007F6 B031                    	mov	al, '1'
  1247 000007F8 66AB                    	stosw
  1248 000007FA 88D8                    	mov	al, bl
  1249 000007FC 2C0A                    	sub	al, 10
  1250                                  iix:
  1251 000007FE 0430                    	add	al, '0'
  1252 00000800 66AB                    	stosw
  1253 00000802 B020                    	mov	al, ' '
  1254 00000804 66AB                    	stosw
  1255 00000806 B021                    	mov	al, '!'
  1256 00000808 66AB                    	stosw
  1257 0000080A B020                    	mov	al, ' '
  1258 0000080C 66AB                    	stosw
  1259                                  	; 23/02/2015
  1260 0000080E 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1261                                  	;jna	iiret
  1262                                  	; 27/02/2022
  1263 00000811 7604                    	jna	short iiz
  1264                                  iiy:
  1265 00000813 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1266 00000815 E6A0                    	out	0A0h, al ; the 2nd 8259
  1267                                  iiz:
  1268 00000817 E983010000              	jmp     iiret
  1269                                  	;
  1270                                  	; 22/08/2014
  1271                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1272                                  	;out	20h, al	; 8259 PORT
  1273                                  	;
  1274                                  	;pop	es
  1275                                  	;pop	ds
  1276                                  	;pop	edi
  1277                                  	;pop	esi
  1278                                  	;pop	ebx
  1279                                  	;pop 	eax
  1280                                  	;iret
  1281                                  
  1282                                  	; 02/04/2015
  1283                                  	; 25/08/2014
  1284                                  exc0:
  1285 0000081C 6A00                            push 	dword 0
  1286 0000081E E990000000                      jmp     cpu_except
  1287                                  exc1:
  1288 00000823 6A01                            push 	dword 1
  1289 00000825 E989000000                      jmp     cpu_except
  1290                                  exc2:
  1291 0000082A 6A02                            push 	dword 2
  1292 0000082C E982000000                      jmp     cpu_except
  1293                                  exc3:
  1294 00000831 6A03                            push 	dword 3
  1295 00000833 EB7E                            jmp     cpu_except
  1296                                  exc4:
  1297 00000835 6A04                            push 	dword 4
  1298 00000837 EB7A                            jmp     cpu_except
  1299                                  exc5:
  1300 00000839 6A05                            push 	dword 5
  1301 0000083B EB76                            jmp     cpu_except
  1302                                  exc6:
  1303 0000083D 6A06                            push 	dword 6
  1304 0000083F EB72                            jmp     cpu_except
  1305                                  exc7:
  1306 00000841 6A07                            push 	dword 7
  1307 00000843 EB6E                            jmp     cpu_except
  1308                                  exc8:
  1309                                  	; [esp] = Error code
  1310 00000845 6A08                            push 	dword 8
  1311 00000847 EB5C                            jmp     cpu_except_en
  1312                                  exc9:
  1313 00000849 6A09                            push 	dword 9
  1314 0000084B EB66                            jmp     cpu_except
  1315                                  exc10:
  1316                                  	; [esp] = Error code
  1317 0000084D 6A0A                            push 	dword 10
  1318 0000084F EB54                            jmp     cpu_except_en
  1319                                  exc11:
  1320                                  	; [esp] = Error code
  1321 00000851 6A0B                            push 	dword 11
  1322 00000853 EB50                            jmp     cpu_except_en
  1323                                  exc12:
  1324                                  	; [esp] = Error code
  1325 00000855 6A0C                            push 	dword 12
  1326 00000857 EB4C                            jmp     cpu_except_en
  1327                                  exc13:
  1328                                  	; [esp] = Error code
  1329 00000859 6A0D                            push 	dword 13
  1330 0000085B EB48                            jmp     cpu_except_en
  1331                                  exc14:
  1332                                  	; [esp] = Error code
  1333 0000085D 6A0E                            push 	dword 14
  1334 0000085F EB44                    	jmp	short cpu_except_en
  1335                                  exc15:
  1336 00000861 6A0F                            push 	dword 15
  1337 00000863 EB4E                            jmp     cpu_except
  1338                                  exc16:
  1339 00000865 6A10                            push 	dword 16
  1340 00000867 EB4A                            jmp     cpu_except
  1341                                  exc17:
  1342                                  	; [esp] = Error code
  1343 00000869 6A11                            push 	dword 17
  1344 0000086B EB38                    	jmp	short cpu_except_en
  1345                                  exc18:
  1346 0000086D 6A12                            push 	dword 18
  1347 0000086F EB42                    	jmp	short cpu_except
  1348                                  exc19:
  1349 00000871 6A13                            push 	dword 19
  1350 00000873 EB3E                    	jmp	short cpu_except
  1351                                  exc20:
  1352 00000875 6A14                            push 	dword 20
  1353 00000877 EB3A                    	jmp	short cpu_except
  1354                                  exc21:
  1355 00000879 6A15                            push 	dword 21
  1356 0000087B EB36                    	jmp	short cpu_except
  1357                                  exc22:
  1358 0000087D 6A16                            push 	dword 22
  1359 0000087F EB32                    	jmp	short cpu_except
  1360                                  exc23:
  1361 00000881 6A17                            push 	dword 23
  1362 00000883 EB2E                    	jmp	short cpu_except
  1363                                  exc24:
  1364 00000885 6A18                            push 	dword 24
  1365 00000887 EB2A                    	jmp	short cpu_except
  1366                                  exc25:
  1367 00000889 6A19                            push 	dword 25
  1368 0000088B EB26                    	jmp	short cpu_except
  1369                                  exc26:
  1370 0000088D 6A1A                            push 	dword 26
  1371 0000088F EB22                    	jmp	short cpu_except
  1372                                  exc27:
  1373 00000891 6A1B                            push 	dword 27
  1374 00000893 EB1E                    	jmp	short cpu_except
  1375                                  exc28:
  1376 00000895 6A1C                            push 	dword 28
  1377 00000897 EB1A                    	jmp	short cpu_except
  1378                                  exc29:
  1379 00000899 6A1D                            push 	dword 29
  1380 0000089B EB16                    	jmp	short cpu_except
  1381                                  exc30:
  1382 0000089D 6A1E                            push 	dword 30
  1383 0000089F EB04                    	jmp	short cpu_except_en
  1384                                  exc31:
  1385 000008A1 6A1F                            push 	dword 31
  1386 000008A3 EB0E                            jmp     short cpu_except
  1387                                  
  1388                                  	; 27/02/2022
  1389                                  	; 19/10/2015
  1390                                  	; 19/09/2015
  1391                                  	; 01/09/2015
  1392                                  	; 28/08/2015
  1393                                  	; 28/08/2014
  1394                                  cpu_except_en:
  1395 000008A5 87442404                	xchg	eax, [esp+4] ; Error code
  1396 000008A9 36A3[E4610000]          	mov	[ss:error_code], eax
  1397 000008AF 58                      	pop	eax  ; Exception number
  1398 000008B0 870424                  	xchg	eax, [esp]
  1399                                  		; eax = eax before exception
  1400                                  		; [esp] -> exception number
  1401                                  		; [esp+4] -> EIP to return
  1402                                  	; 19/10/2015
  1403                                  	; 19/09/2015
  1404                                  	; 01/09/2015
  1405                                  	; 28/08/2015
  1406                                  	; 29/08/2014
  1407                                  	; 28/08/2014
  1408                                  	; 25/08/2014
  1409                                  	; 21/08/2014
  1410                                  cpu_except:	; CPU Exceptions
  1411 000008B3 FC                      	cld
  1412 000008B4 870424                  	xchg	eax, [esp] 
  1413                                  		; eax = Exception number
  1414                                  		; [esp] = eax (before exception)	
  1415 000008B7 53                      	push	ebx
  1416 000008B8 56                      	push	esi
  1417 000008B9 57                      	push	edi
  1418 000008BA 1E                      	push 	ds
  1419 000008BB 06                      	push 	es
  1420                                  	; 28/08/2015
  1421 000008BC 66BB1000                	mov	bx, KDATA
  1422 000008C0 8EDB                    	mov	ds, bx
  1423 000008C2 8EC3                    	mov	es, bx
  1424 000008C4 0F20DB                  	mov	ebx, cr3
  1425 000008C7 53                      	push	ebx ; (*) page directory
  1426                                  	; 19/10/2015
  1427 000008C8 FC                      	cld
  1428                                  	; 25/03/2015
  1429 000008C9 8B1D[38610000]          	mov	ebx, [k_page_dir]
  1430 000008CF 0F22DB                  	mov	cr3, ebx
  1431                                  	; 28/08/2015
  1432 000008D2 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT	
  1433 000008D5 7513                    	jne	short cpu_except_nfp
  1434 000008D7 E8B61D0000              	call	page_fault_handler
  1435 000008DC 21C0                    	and 	eax, eax
  1436                                          ;jz	iiretp ; 01/09/2015
  1437                                  	; 27/02/2022
  1438 000008DE 7505                    	jnz	short cpu_except_pf
  1439 000008E0 E9B6000000              	jmp	iiretp
  1440                                  cpu_except_pf:
  1441 000008E5 B80E000000              	mov	eax, 0Eh ; 14
  1442                                  cpu_except_nfp:
  1443                                  	; 02/04/2015
  1444 000008EA BB[15060000]            	mov	ebx, hang
  1445 000008EF 875C241C                	xchg	ebx, [esp+28]
  1446                                  		; EIP (points to instruction which faults)
  1447                                  	  	; New EIP (hang)
  1448 000008F3 891D[E8610000]          	mov	[FaultOffset], ebx
  1449 000008F9 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1450 00000901 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1451                                  	;
  1452 00000909 88C4                    	mov	ah, al
  1453 0000090B 240F                    	and	al, 0Fh
  1454 0000090D 3C09                    	cmp	al, 9
  1455 0000090F 7602                    	jna	short h1ok
  1456 00000911 0407                    	add	al, 'A'-':'
  1457                                  h1ok:
  1458 00000913 D0EC                    	shr	ah, 1
  1459 00000915 D0EC                    	shr	ah, 1
  1460 00000917 D0EC                    	shr	ah, 1
  1461 00000919 D0EC                    	shr	ah, 1
  1462 0000091B 80FC09                  	cmp	ah, 9
  1463 0000091E 7603                    	jna	short h2ok
  1464 00000920 80C407                  	add	ah, 'A'-':'
  1465                                  h2ok:	
  1466 00000923 86E0                    	xchg 	ah, al	
  1467 00000925 66053030                	add	ax, '00'
  1468 00000929 66A3[185D0000]          	mov	[excnstr], ax
  1469                                  	;
  1470                                  	; 29/08/2014
  1471 0000092F A1[E8610000]            	mov	eax, [FaultOffset]
  1472 00000934 51                      	push	ecx
  1473 00000935 52                      	push	edx
  1474 00000936 89E3                    	mov	ebx, esp
  1475                                  	; 28/08/2015
  1476 00000938 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1477                                  			  ; to hexadecimal string
  1478                                  	;mov	ecx, 10	    ; divisor to convert	
  1479                                  			    ; binary number to decimal string
  1480                                  b2d1:
  1481 0000093D 31D2                    	xor	edx, edx
  1482 0000093F F7F1                    	div	ecx
  1483                                  	;push	dx
  1484                                  	; 27/02/2022
  1485 00000941 52                      	push	edx
  1486 00000942 39C8                    	cmp	eax, ecx
  1487 00000944 73F7                    	jnb	short b2d1
  1488 00000946 BF[235D0000]            	mov	edi, EIPstr ; EIP value
  1489                                  			    ; points to instruction which faults	
  1490                                  	; 28/08/2015
  1491 0000094B 89C2                    	mov	edx, eax
  1492                                  b2d2:
  1493                                  	;add	al, '0'
  1494 0000094D 8A82[F5150000]          	mov	al, [edx+hexchrs]
  1495 00000953 AA                      	stosb		    ; write hexadecimal digit to its place	
  1496 00000954 39E3                    	cmp	ebx, esp
  1497 00000956 7605                    	jna	short b2d3
  1498                                  	; 27/02/2022
  1499 00000958 58                      	pop	eax
  1500                                  	;pop	ax
  1501 00000959 88C2                    	mov	dl, al
  1502 0000095B EBF0                    	jmp	short b2d2
  1503                                  b2d3:
  1504 0000095D B068                    	mov 	al, 'h' ; 28/08/2015
  1505 0000095F AA                      	stosb
  1506 00000960 B020                    	mov	al, 20h	    ; space
  1507 00000962 AA                      	stosb
  1508 00000963 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1509 00000965 AA                      	stosb
  1510                                  	;
  1511 00000966 5A                      	pop	edx
  1512 00000967 59                      	pop	ecx
  1513                                  	;
  1514 00000968 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1515                                  			; white (F) forecolor
  1516 0000096A BE[085D0000]            	mov	esi, exc_msg ; message offset
  1517                                  	;
  1518 0000096F EB11                    	jmp	short piemsg
  1519                                  	;
  1520                                          ;add    dword [scr_row], 0A0h
  1521                                          ;mov    edi, [scr_row]
  1522                                          ;
  1523                                  	;call 	printk
  1524                                  	;
  1525                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1526                                  	;out	20h, al	; 8259 PORT
  1527                                  	;
  1528                                  	;pop	es
  1529                                  	;pop	ds
  1530                                  	;pop	edi
  1531                                  	;pop	esi
  1532                                  	;pop 	eax
  1533                                  	;iret
  1534                                  	
  1535                                  	; 28/08/2015
  1536                                  	; 23/02/2015
  1537                                  	; 20/08/2014
  1538                                  ignore_int:
  1539 00000971 50                      	push	eax
  1540 00000972 53                      	push	ebx ; 23/02/2015
  1541 00000973 56                      	push	esi
  1542 00000974 57                      	push	edi
  1543 00000975 1E                      	push 	ds
  1544 00000976 06                      	push 	es
  1545                                  	; 28/08/2015
  1546 00000977 0F20D8                  	mov	eax, cr3
  1547 0000097A 50                      	push	eax ; (*) page directory
  1548                                  	;
  1549 0000097B B467                    	mov	ah, 67h	; brown (6) background, 
  1550                                  			; light gray (7) forecolor
  1551 0000097D BE[C65C0000]            	mov	esi, int_msg ; message offset
  1552                                  piemsg:
  1553                                          ; 27/08/2014
  1554 00000982 8105[8C5C0000]A000-             add     dword [scr_row], 0A0h
  1554 0000098A 0000               
  1555 0000098C 8B3D[8C5C0000]                  mov     edi, [scr_row]
  1556                                          ;
  1557 00000992 E8B7FCFFFF              	call 	printk
  1558                                  	;
  1559                                  	; 23/02/2015
  1560 00000997 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1561 00000999 E6A0                    	out	0A0h, al ; the 2nd 8259
  1562                                  iiretp: ; 01/09/2015
  1563                                  	; 28/08/2015
  1564 0000099B 58                      	pop	eax ; (*) page directory
  1565 0000099C 0F22D8                  	mov	cr3, eax
  1566                                  	;
  1567                                  iiret:
  1568                                  	; 22/08/2014
  1569 0000099F B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1570 000009A1 E620                    	out	20h, al	; 8259 PORT
  1571                                  	;
  1572 000009A3 07                      	pop	es
  1573 000009A4 1F                      	pop	ds
  1574 000009A5 5F                      	pop	edi
  1575 000009A6 5E                      	pop	esi
  1576 000009A7 5B                      	pop	ebx ; 29/08/2014
  1577 000009A8 58                      	pop 	eax
  1578 000009A9 CF                      	iretd
  1579                                  
  1580                                  	; 23/02/2022
  1581                                  	; 26/02/2015
  1582                                  	; 07/09/2014
  1583                                  	; 25/08/2014
  1584                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1585                                  	; 22/08/2014
  1586 000009AA 50                      	push	eax
  1587 000009AB 53                      	push	ebx ; 29/08/2014
  1588 000009AC 56                      	push	esi
  1589 000009AD 57                      	push	edi
  1590 000009AE 1E                      	push 	ds
  1591 000009AF 06                      	push 	es
  1592                                  	;
  1593 000009B0 B810000000              	mov	eax, KDATA
  1594 000009B5 8ED8                    	mov	ds, ax
  1595 000009B7 8EC0                    	mov	es, ax
  1596                                  	;
  1597                                  	; 25/08/2014
  1598                                  	;call	rtc_p
  1599                                  	; 23/02/2022
  1600 000009B9 FF15[0D070000]          	call	[x_rtci]
  1601                                  	;
  1602                                  	; 22/02/2015 - dsectpm.s
  1603                                  	; [ source: http://wiki.osdev.org/RTC ]
  1604                                  	; read status register C to complete procedure
  1605                                  	;(it is needed to get a next IRQ 8) 
  1606 000009BF B00C                    	mov	al, 0Ch ; 
  1607 000009C1 E670                    	out	70h, al ; select register C
  1608 000009C3 90                      	nop
  1609 000009C4 E471                    	in	al, 71h ; just throw away contents
  1610                                  	; 22/02/2015
  1611 000009C6 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1612 000009C8 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1613                                  	;
  1614 000009CA EBD3                    	jmp	short iiret	
  1615                                  
  1616                                  	; 22/08/2014
  1617                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1618                                  	; (INT 1Ah)
  1619                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1620                                  time_of_day:
  1621 000009CC E868010000              	call	UPD_IPR			; WAIT TILL UPDATE NOT IN PROGRESS
  1622 000009D1 726F                            jc      short rtc_retn 
  1623 000009D3 B000                    	mov	al, CMOS_SECONDS
  1624 000009D5 E847010000              	call	CMOS_READ
  1625 000009DA A2[AC610000]            	mov	[time_seconds], al 
  1626 000009DF B002                    	mov	al, CMOS_MINUTES
  1627 000009E1 E83B010000              	call	CMOS_READ
  1628 000009E6 A2[AD610000]            	mov	[time_minutes], al 
  1629 000009EB B004                    	mov	al, CMOS_HOURS
  1630 000009ED E82F010000              	call	CMOS_READ
  1631 000009F2 A2[AE610000]                    mov     [time_hours], al
  1632 000009F7 B006                    	mov	al, CMOS_DAY_WEEK 
  1633 000009F9 E823010000              	call	CMOS_READ
  1634 000009FE A2[AF610000]            	mov	[date_wday], al
  1635 00000A03 B007                     	mov	al, CMOS_DAY_MONTH
  1636 00000A05 E817010000              	call	CMOS_READ
  1637 00000A0A A2[B0610000]            	mov	[date_day], al
  1638 00000A0F B008                    	mov	al, CMOS_MONTH
  1639 00000A11 E80B010000              	call	CMOS_READ
  1640 00000A16 A2[B1610000]            	mov	[date_month], al
  1641 00000A1B B009                    	mov	al, CMOS_YEAR
  1642 00000A1D E8FF000000              	call	CMOS_READ
  1643 00000A22 A2[B2610000]            	mov	[date_year], al
  1644 00000A27 B032                    	mov	al, CMOS_CENTURY
  1645 00000A29 E8F3000000              	call	CMOS_READ
  1646 00000A2E A2[B3610000]            	mov	[date_century], al
  1647                                  	;
  1648 00000A33 B000                    	mov	al, CMOS_SECONDS
  1649 00000A35 E8E7000000              	call 	CMOS_READ
  1650 00000A3A 3A05[AC610000]          	cmp	al, [time_seconds]
  1651 00000A40 758A                    	jne	short time_of_day
  1652                                  
  1653                                  rtc_retn:
  1654 00000A42 C3                      	retn
  1655                                  
  1656                                  rtci_default:
  1657                                  	; 23/02/2022 (Temporary!)
  1658                                  	; (default real time clock handler in multitasking mode)
  1659                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1660 00000A43 FF05[F0610000]          	inc	dword [rtc_ticks] ; real time clock counter
  1661                                  			; (not used in anywhere of kernel for now!)
  1662 00000A49 C3                      	retn
  1663                                  
  1664                                  rtc_p:	
  1665                                  	; 27/02/2022
  1666                                  	; 12/02/2022
  1667                                  	; 07/09/2014
  1668                                  	; 29/08/2014
  1669                                  	; 27/08/2014
  1670                                  	; 25/08/2014
  1671                                   	; Print Real Time Clock content
  1672                                  	;
  1673                                  	;
  1674 00000A4A E87DFFFFFF              	call	time_of_day
  1675 00000A4F 72F1                    	jc	short rtc_retn
  1676                                  	;
  1677 00000A51 3A05[7A5D0000]          	cmp	al, [ptime_seconds]
  1678 00000A57 74E9                            je      short rtc_retn ; 29/08/2014
  1679                                  	;
  1680 00000A59 A2[7A5D0000]            	mov	[ptime_seconds], al
  1681                                  	;
  1682 00000A5E A0[B3610000]            	mov	al, [date_century]
  1683 00000A63 E8EC000000              	call	bcd_to_ascii
  1684 00000A68 66A3[475D0000]          	mov	[datestr+6], ax
  1685 00000A6E A0[B2610000]            	mov	al, [date_year]
  1686 00000A73 E8DC000000              	call	bcd_to_ascii
  1687 00000A78 66A3[495D0000]          	mov	[datestr+8], ax
  1688 00000A7E A0[B1610000]            	mov	al, [date_month]
  1689 00000A83 E8CC000000              	call	bcd_to_ascii
  1690 00000A88 66A3[445D0000]          	mov	[datestr+3], ax
  1691 00000A8E A0[B0610000]            	mov	al, [date_day]
  1692 00000A93 E8BC000000              	call	bcd_to_ascii
  1693 00000A98 66A3[415D0000]          	mov	[datestr], ax
  1694                                  	;
  1695 00000A9E 0FB61D[AF610000]        	movzx	ebx, byte [date_wday]
  1696 00000AA5 C0E302                  	shl 	bl, 2
  1697 00000AA8 81C3[5A5D0000]          	add	ebx, daytmp
  1698 00000AAE 8B03                    	mov	eax, [ebx]
  1699 00000AB0 A3[4C5D0000]            	mov	[daystr], eax
  1700                                  	;
  1701 00000AB5 A0[AE610000]            	mov	al, [time_hours]
  1702 00000ABA E895000000              	call	bcd_to_ascii
  1703 00000ABF 66A3[505D0000]          	mov	[timestr], ax
  1704 00000AC5 A0[AD610000]            	mov	al, [time_minutes]
  1705 00000ACA E885000000              	call	bcd_to_ascii
  1706 00000ACF 66A3[535D0000]          	mov	[timestr+3], ax
  1707 00000AD5 A0[AC610000]            	mov	al, [time_seconds]
  1708 00000ADA E875000000              	call	bcd_to_ascii
  1709 00000ADF 66A3[565D0000]          	mov	[timestr+6], ax
  1710                                  	;		
  1711 00000AE5 BE[2F5D0000]            	mov	esi, rtc_msg ; message offset
  1712                                  	; 23/02/2015
  1713 00000AEA 52                      	push	edx
  1714 00000AEB 51                      	push	ecx
  1715                                  	; 07/09/2014
  1716                                  	;mov	bx, 2	; Video page 2
  1717                                  	; 27/02/2022
  1718 00000AEC 29DB                    	sub	ebx, ebx
  1719 00000AEE B307                    	mov	bl, 7	; Video page 7
  1720                                  prtmsg:
  1721 00000AF0 AC                      	lodsb
  1722 00000AF1 08C0                    	or	al, al
  1723 00000AF3 740D                    	jz	short prtmsg_ok
  1724 00000AF5 56                      	push	esi
  1725                                  	; 27/02/2022
  1726 00000AF6 53                      	push	ebx
  1727                                  	;push	bx
  1728 00000AF7 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1729                                  			; white (F) forecolor
  1730 00000AF9 E8B7070000              	call 	write_tty
  1731                                  	;pop	bx
  1732                                  	; 27/02/2022
  1733 00000AFE 5B                      	pop	ebx
  1734 00000AFF 5E                      	pop	esi
  1735 00000B00 EBEE                    	jmp	short prtmsg
  1736                                  	;
  1737                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1738                                  	;call	printk
  1739                                  prtmsg_ok:
  1740                                  	; 07/09/2014
  1741                                  	;xor	dx, dx		; column 0, row 0
  1742                                  	; 27/02/2022
  1743 00000B02 31D2                    	xor	edx, edx
  1744 00000B04 E8B6080000              	call	set_cpos	; set cursor position to 0,0 
  1745                                  	; 23/02/2015
  1746 00000B09 59                      	pop	ecx
  1747 00000B0A 5A                      	pop	edx
  1748 00000B0B C3                      	retn
  1749                                  
  1750                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1751                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1752                                  default_irq7:
  1753                                  	; 27/02/2022
  1754                                  	;push	ax
  1755 00000B0C 50                      	push	eax
  1756 00000B0D B00B                    	mov	al, 0Bh  ; In-Service register
  1757 00000B0F E620                    	out	20h, al
  1758 00000B11 EB00                            jmp short $+2
  1759 00000B13 EB00                    	jmp short $+2
  1760 00000B15 E420                    	in	al, 20h
  1761 00000B17 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1762 00000B19 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1763 00000B1B B020                            mov     al, 20h ; EOI
  1764 00000B1D E620                    	out	20h, al 
  1765                                  irq7_iret:
  1766                                  	;pop	ax
  1767                                  	; 27/02/2022
  1768 00000B1F 58                      	pop	eax
  1769 00000B20 CF                      	iretd
  1770                                  	
  1771                                  	; 22/08/2014
  1772                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1773                                  CMOS_READ:
  1774 00000B21 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1775 00000B22 D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1776 00000B24 F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1777 00000B25 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1778 00000B27 FA                      	cli		; DISABLE INTERRUPTS
  1779 00000B28 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1780 00000B2A 90                      	nop		; I/O DELAY
  1781 00000B2B E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1782 00000B2D 6650                    	push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1783                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1784                                  		     ; ----- 10/06/85 (test4.asm)
  1785 00000B2F B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1786                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1787 00000B31 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1788 00000B33 E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1789 00000B35 6658                    	pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1790 00000B37 9D                      	popf	
  1791 00000B38 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1792                                  
  1793                                  	; 22/08/2014
  1794                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1795                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1796 00000B39 51                      	push	ecx
  1797 00000B3A B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1798                                  		; mov cx, 800	
  1799                                  UPD_10:
  1800 00000B3F B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1801 00000B41 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1802 00000B42 E8DAFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1803 00000B47 A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1804 00000B49 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1805 00000B4B FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1806 00000B4C E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1807 00000B4E 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1808                                  		; xor ax, ax
  1809 00000B50 F9                      	stc				; SET CARRY FOR ERROR
  1810                                  UPD_90:
  1811 00000B51 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1812 00000B52 FA                      	cli				; INTERRUPTS OFF DURING SET
  1813 00000B53 C3                      	retn				; RETURN WITH CY FLAG SET
  1814                                  
  1815                                  bcd_to_ascii:
  1816                                  	; 25/08/2014
  1817                                  	; INPUT ->
  1818                                  	;	al = Packed BCD number
  1819                                  	; OUTPUT ->
  1820                                  	;	ax  = ASCII word/number
  1821                                  	;
  1822                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1823                                  	;
  1824 00000B54 D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1825                                  					; AH = AL / 10h
  1826                                  					; AL = AL MOD 10h
  1827 00000B56 660D3030                	or ax,'00'                      ; Make it ASCII based
  1828                                  
  1829 00000B5A 86E0                            xchg ah, al 
  1830                                  	
  1831 00000B5C C3                      	retn	
  1832                                  	
  1833                                  %include 'keyboard.inc' ; 07/03/2015
  1834                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - KEYBOARD.INC
  1835                              <1> ; Last Modification: 24/07/2022
  1836                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1837                              <1> ;
  1838                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1839                              <1> 
  1840                              <1> ; 24/07/2022 (Retro UNIX 386 v1, Kernel v0.2.0.22) 
  1841                              <1> ; 13/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20)
  1842                              <1> ; 23/02/2022 
  1843                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1844                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1845                              <1> ; 30/06/2015
  1846                              <1> ; 11/03/2015
  1847                              <1> ; 28/02/2015
  1848                              <1> ; 25/02/2015
  1849                              <1> ; 20/02/2015
  1850                              <1> ; 18/02/2015
  1851                              <1> ; 03/12/2014
  1852                              <1> ; 07/09/2014
  1853                              <1> ; KEYBOARD INTERRUPT HANDLER
  1854                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1855                              <1> 
  1856                              <1> ;getch:
  1857                              <1> ;	; 18/02/2015
  1858                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1859                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1860                              <1> ;	; routine, later... (multi tasking ability)
  1861                              <1> ;	; 28/02/2015
  1862                              <1> ;	sti	; enable interrupts
  1863                              <1> ;	;
  1864                              <1> ;	;push	esi
  1865                              <1> ;	;push	ebx
  1866                              <1> ;	;xor	ebx, ebx
  1867                              <1> ;	;mov	bl, [ptty]  ; active_page
  1868                              <1> ;	;mov	esi, ebx
  1869                              <1> ;	;shl 	si, 1
  1870                              <1> ;	;add	esi, ttychr
  1871                              <1> ;getch_1:
  1872                              <1> ;	;mov	ax, [esi]
  1873                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1874                              <1> ;	and	ax, ax
  1875                              <1> ;	jz	short getch_2
  1876                              <1> ;	mov	word [ttychr], 0
  1877                              <1> ;	;mov	word [esi], 0
  1878                              <1> ;	;pop	ebx
  1879                              <1> ;	;pop	esi
  1880                              <1> ;	retn
  1881                              <1> ;getch_2:
  1882                              <1> ;	hlt	; not proper for multi tasking!
  1883                              <1> ;		; (temporary halt for now)
  1884                              <1> ;		; 'sleep' on tty 
  1885                              <1> ;		; will (must) be located here		
  1886                              <1> ;	nop
  1887                              <1> ;	jmp	short getch_1
  1888                              <1> 
  1889                              <1> keyb_int:
  1890                              <1> 	; 24/07/2022
  1891                              <1> 	; 23/02/2022
  1892                              <1> 	; 30/06/2015
  1893                              <1> 	; 25/02/2015
  1894                              <1> 	; 20/02/2015
  1895                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1896                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1897                              <1> 	; 30/06/2014
  1898                              <1> 	; 10/05/2013	
  1899                              <1>       	; Retro Unix 8086 v1 feature only!
  1900                              <1> 	; 03/03/2014
  1901                              <1> 	
  1902 00000B5D 1E                  <1> 	push	ds
  1903 00000B5E 53                  <1> 	push	ebx
  1904 00000B5F 50                  <1> 	push	eax
  1905                              <1> 	;
  1906                              <1> 	; 23/02/2022
  1907 00000B60 9C                  <1> 	pushfd
  1908 00000B61 0E                  <1> 	push	cs
  1909                              <1> 	;mov	ax, KDATA
  1910 00000B62 31C0                <1> 	xor	eax, eax
  1911 00000B64 B010                <1> 	mov	al, KDATA
  1912 00000B66 8ED8                <1> 	mov	ds, ax
  1913                              <1> 	;
  1914                              <1> 	;pushfd
  1915                              <1> 	;push	cs
  1916 00000B68 E80A010000          <1> 	call	kb_int   ; int_09h
  1917                              <1> 	;
  1918                              <1> 	;mov	ah, 11h	 ; 03/12/2014	
  1919 00000B6D B401                <1> 	mov	ah, 1 ; 24/07/2022
  1920                              <1> 	;call	getc
  1921 00000B6F E854000000          <1> 	call	int_16h  ; 30/06/2015
  1922 00000B74 744E                <1> 	jz	short keyb_int4
  1923                              <1> 	;
  1924                              <1> 	;mov	ah, 10h	 ; 03/12/2014
  1925 00000B76 B400                <1> 	mov	ah, 0 ; 24/07/2022
  1926                              <1> 	;call	getc
  1927 00000B78 E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1928                              <1> 	;
  1929                              <1> 	; 20/02/2015
  1930 00000B7D 0FB61D[66610000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1931                              <1> 	;
  1932 00000B84 20C0                <1> 	and 	al, al
  1933 00000B86 751D                <1> 	jnz	short keyb_int1
  1934                              <1> 	;
  1935 00000B88 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1936 00000B8B 7218                <1> 	jb	short keyb_int1
  1937 00000B8D 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1938 00000B90 7713                <1> 	ja	short keyb_int1
  1939                              <1> 	;
  1940 00000B92 88D8                <1> 	mov	al, bl
  1941 00000B94 0468                <1> 	add	al, 68h
  1942 00000B96 38E0                <1> 	cmp	al, ah
  1943 00000B98 7409                <1> 	je	short keyb_int0
  1944 00000B9A 88E0                <1> 	mov	al, ah
  1945 00000B9C 2C68                <1> 	sub	al, 68h
  1946 00000B9E E831090000          <1> 	call	tty_sw
  1947                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1948                              <1> keyb_int0: ; 30/06/2015
  1949                              <1> 	;xor	ax, ax
  1950                              <1> 	; 23/02/2022
  1951 00000BA3 31C0                <1> 	xor	eax, eax
  1952                              <1> keyb_int1:
  1953 00000BA5 D0E3                <1> 	shl	bl, 1
  1954 00000BA7 81C3[68610000]      <1> 	add	ebx, ttychr
  1955                              <1> 	;
  1956                              <1> 	;23/02/2022
  1957 00000BAD 09C0                <1> 	or	eax, eax
  1958                              <1> 	;or	ax, ax
  1959 00000BAF 7406                <1> 	jz	short keyb_int2
  1960                              <1> 	;
  1961 00000BB1 66833B00            <1> 	cmp 	word [ebx], 0
  1962 00000BB5 7703                <1>         ja      short keyb_int3 
  1963                              <1> keyb_int2:
  1964 00000BB7 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1965                              <1> 			   ; and scan code of the character
  1966                              <1> 			   ; for current tty (or last tty
  1967                              <1> 			   ; just before tty switch).
  1968                              <1> keyb_int3:
  1969 00000BBA A0[66610000]        <1>         mov     al, [ptty]
  1970 00000BBF E8233A0000          <1> 	call	wakeup
  1971                              <1> 	;
  1972                              <1> keyb_int4:
  1973 00000BC4 58                  <1> 	pop	eax
  1974 00000BC5 5B                  <1> 	pop	ebx
  1975 00000BC6 1F                  <1> 	pop	ds
  1976 00000BC7 CF                  <1> 	iret
  1977                              <1> 
  1978                              <1> ; 18/02/2015
  1979                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1980                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1981                              <1> ; scancode and ascii code of the character 
  1982                              <1> ; in the tty input (ttychr) buffer. 
  1983                              <1> ; Test procedures must call 'getch' for tty input
  1984                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1985                              <1> ; due to infinite (key press) waiting loop.
  1986                              <1> ; 
  1987                              <1> ; 03/12/2014
  1988                              <1> ; 26/08/2014
  1989                              <1> ; KEYBOARD I/O
  1990                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1991                              <1> 
  1992                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1993                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1994                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1995                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1996                              <1> 
  1997                              <1> 
  1998                              <1> ; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  1999                              <1> ;int_16h: ; 30/06/2015
  2000                              <1> ;;getc:
  2001                              <1> ;	pushfd	; 28/08/2014
  2002                              <1> ;	push 	cs
  2003                              <1> ;	call 	getc_int
  2004                              <1> ;	retn
  2005                              <1> 
  2006                              <1> 	; 24/07/2022
  2007                              <1> %if 0
  2008                              <1> ; 24/12/2021
  2009                              <1> 
  2010                              <1> 	;-----	SHIFT STATUS
  2011                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2012                              <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2013                              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2014                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2015                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2016                              <1>         shl	ah, 5
  2017                              <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2018                              <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2019                              <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2020                              <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2021                              <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2022                              <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2023                              <1> _K3:
  2024                              <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2025                              <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2026                              <1> 
  2027                              <1> %endif
  2028                              <1> 
  2029                              <1> int_16h:
  2030                              <1> 	; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2031                              <1> 	; 24/07/2022 - (near call return instead of interrupt return)
  2032                              <1> 	
  2033                              <1> 	; INPUT:
  2034                              <1> 	;	AH = Function (0 or 1)
  2035                              <1> 	;	     0 = Read Character
  2036                              <1> 	;	     1 = Get Keyboard Buffer Status
  2037                              <1> 	; OUTPUT:
  2038                              <1> 	;	Function 0 - AX = ASCII (AL) and SCAN CODE (AH)
  2039                              <1> 	;			  of the character (enterrd from the keyboard) 
  2040                              <1> 	;	Function 1 - If ZF = 0
  2041                              <1> 	;			AX = ASCII (AL) and SCAN CODE (AH) of the character
  2042                              <1> 	;			(which is waiting in keyboard buffer)
  2043                              <1> 	;		     If ZF = 1
  2044                              <1> 	;			there is not a character in the keyboard buffer
  2045                              <1> 	;
  2046                              <1> 	; Modified registers: eax, ebx
  2047                              <1> 	
  2048                              <1> getc_int:
  2049                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2050                              <1> 	; 28/02/2015
  2051                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2052                              <1> 	;	      instead of pc-at bios - 1985-)
  2053                              <1> 	; 28/08/2014 (_k1d)
  2054                              <1> 	; 30/06/2014
  2055                              <1> 	; 03/03/2014
  2056                              <1> 	; 28/02/2014
  2057                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2058                              <1> 	; rombios source code (21/04/1986)
  2059                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2060                              <1> 	;
  2061                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2062                              <1> 	;
  2063                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2064                              <1> 	; KEYBOARD I/O								      :
  2065                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2066                              <1> 	; INPUT									      :
  2067                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2068                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2069                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2070                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2071                              <1> 	;-----------------------------------------------------------------------------:
  2072                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2073                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2074                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2075                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2076                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2077                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2078                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2079                              <1> 	;-----------------------------------------------------------------------------:	
  2080                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2081                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2082                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2083                              <1> 	;-----------------------------------------------------------------------------:	
  2084                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2085                              <1> 	;	      (AL) = 05H                                                      :
  2086                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2087                              <1> 	;		       							      :
  2088                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2089                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2090                              <1> 	;                     --------------------------------------------            :
  2091                              <1> 	;			00H        30.0        10H        7.5                 :
  2092                              <1> 	;			01H        26.7        11H        6.7                 :
  2093                              <1> 	;			02H        24.0        12H        6.0                 :
  2094                              <1> 	;			03H        21.8        13H        5.5                 :
  2095                              <1> 	;			04H        20.0        14H        5.0                 :
  2096                              <1> 	;			05H        18.5        15H        4.6                 :
  2097                              <1> 	;			06H        17.1        16H        4.3                 :
  2098                              <1> 	;			07H        16.0        17H        4.0                 :
  2099                              <1> 	;			08H        15.0        18H        3.7                 :
  2100                              <1> 	;			09H        13.3        19H        3.3                 :
  2101                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2102                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2103                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2104                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2105                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2106                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2107                              <1> 	;									      :
  2108                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2109                              <1> 	;		       							      :
  2110                              <1> 	;                     REGISTER     DELAY                                      :
  2111                              <1> 	;                      VALUE       VALUE                                      :
  2112                              <1> 	;                     ------------------                                      :
  2113                              <1> 	;			00H        250 ms                                     :
  2114                              <1> 	;			01H        500 ms                                     :
  2115                              <1> 	;			02H        750 ms                                     :
  2116                              <1> 	;			03H       1000 ms                                     :
  2117                              <1> 	;-----------------------------------------------------------------------------:
  2118                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2119                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2120                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2121                              <1> 	;		           (CH) = SCAN CODE                                   :
  2122                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2123                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2124                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2125                              <1> 	;-----------------------------------------------------------------------------:		
  2126                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2127                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2128                              <1> 	;-----------------------------------------------------------------------------:
  2129                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2130                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2131                              <1> 	;-----------------------------------------------------------------------------:	
  2132                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2133                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2134                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2135                              <1> 	; OUTPUT					                              :
  2136                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2137                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2138                              <1> 	;------------------------------------------------------------------------------
  2139                              <1> 	
  2140 00000BC8 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2141                              <1> 
  2142                              <1> 	; 24/07/2022
  2143                              <1> 	;push	ds			; SAVE CURRENT DS
  2144                              <1> 	;push	ebx			; SAVE BX TEMPORARILY
  2145                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2146                              <1>         ;mov	bx, KDATA 
  2147                              <1> 	;mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2148                              <1> 
  2149                              <1> 	;or	ah, ah			; CHECK FOR (AH)= 00H
  2150                              <1> 	;jz	short _K1		; ASCII_READ
  2151                              <1> 	;dec	ah                      ; CHECK FOR (AH)= 01H
  2152                              <1> 	;jz	short _K2               ; ASCII_STATUS
  2153                              <1> 	;dec	ah			; CHECK FOR (AH)= 02H
  2154                              <1> 	;jz	short _K3               ; SHIFT STATUS
  2155                              <1> 	;dec	ah			; CHECK FOR (AH)= 03H	
  2156                              <1> 	;jz	short _K300             ; SET TYPAMATIC RATE/DELAY
  2157                              <1> 	;sub	ah, 2			; CHECK FOR (AH)= 05H	
  2158                              <1> 	;jz	short _K500             ; KEYBOARD WRITE         
  2159                              <1> ;_KIO1:	
  2160                              <1> 	;sub	ah, 11			; AH =  10H
  2161                              <1> 	;jz	short _K1E		; EXTENDED ASCII READ
  2162                              <1> 	;dec	ah			; CHECK FOR (AH)= 11H
  2163                              <1> 	;jz	short _K2E		; EXTENDED_ASCII_STATUS
  2164                              <1> 	;dec	ah			; CHECK FOR (AH)= 12H
  2165                              <1> 	;jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2166                              <1> 
  2167                              <1> ;_KIO_EXIT:
  2168                              <1> 	;pop	ecx			; RECOVER REGISTER
  2169                              <1> 	;pop	ebx			; RECOVER REGISTER
  2170                              <1> 	; 24/07/2022
  2171                              <1> 	;retn
  2172                              <1> 	;pop	ds			; RECOVER SEGMENT
  2173                              <1> 	;iretd				; INVALID COMMAND, EXIT
  2174                              <1> 
  2175 00000BC9 08E4                <1> 	or	ah, ah
  2176 00000BCB 7507                <1> 	jnz	short _K2
  2177                              <1> 
  2178                              <1> 	;-----	ASCII CHARACTER
  2179                              <1> _K1:
  2180                              <1> _K1E:	
  2181 00000BCD E81C000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2182                              <1> 	;call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2183                              <1> 	;;jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2184                              <1> 	; 24/07/2022
  2185                              <1> 	;retn
  2186 00000BD2 EB0F                <1> 	jmp	short _KIO_E_XLAT
  2187                              <1> ;_K1:	
  2188                              <1> 	;call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2189                              <1> 	;call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2190                              <1> 	;jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2191                              <1> ;_K1A:
  2192                              <1> 	;jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2193                              <1> 	; 24/07/2022
  2194                              <1> 	;retn
  2195                              <1> 
  2196                              <1> 	;-----	ASCII STATUS
  2197                              <1> _K2:
  2198                              <1> _K2E:	
  2199 00000BD4 E860000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2200 00000BD9 7407                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2201 00000BDB 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2202 00000BDC E802000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2203                              <1> 	;jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2204                              <1> 	; 24/07/2022
  2205 00000BE1 9D                  <1> 	popf
  2206                              <1> _K2B:
  2207 00000BE2 C3                  <1> 	retn
  2208                              <1> ;_K2:	
  2209                              <1> 	;call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2210                              <1> 	;jz	short _K2B		; RETURN IF BUFFER EMPTY
  2211                              <1> 	;pushf				; SAVE ZF FROM TEST
  2212                              <1> 	;call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2213                              <1> 	;jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2214                              <1> 	;popf				; INVALID CODE FOR THIS TYPE OF CALL
  2215                              <1> 	;call	_K1S			; THROW THE CHARACTER AWAY
  2216                              <1> 	;jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2217                              <1> ;_K2A:
  2218                              <1> 	;popf				; RESTORE ZF FROM TEST
  2219                              <1> ;_K2B:
  2220                              <1> 	;;pop	ecx			; RECOVER REGISTER
  2221                              <1> 	;pop	ebx			; RECOVER REGISTER
  2222                              <1> 	;pop	ds			; RECOVER SEGMENT
  2223                              <1> 	;retf	4			; THROW AWAY (E)FLAGS
  2224                              <1> 
  2225                              <1> ; 24/12/2021
  2226                              <1> ;	;-----	SHIFT STATUS
  2227                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2228                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2229                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2230                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2231                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2232                              <1> ;       shl	ah, 5
  2233                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2234                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2235                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2236                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2237                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2238                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2239                              <1> ;_K3:
  2240                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2241                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2242                              <1> 
  2243                              <1> 	; 24/07/2022
  2244                              <1> %if 0
  2245                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2246                              <1> _K300:
  2247                              <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2248                              <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2249                              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2250                              <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2251                              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2252                              <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2253                              <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2254                              <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2255                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2256                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2257                              <1> 	shl	bh, 5
  2258                              <1> 	mov	al, bl			; PUT IN RATE
  2259                              <1> 	or	al, bh			; AND DELAY
  2260                              <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2261                              <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2262                              <1> 
  2263                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2264                              <1> _K500:
  2265                              <1> 	push	esi			; SAVE SI (esi)
  2266                              <1> 	cli				; 
  2267                              <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2268                              <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2269                              <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2270                              <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2271                              <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2272                              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2273                              <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2274                              <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2275                              <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2276                              <1> _K502:
  2277                              <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2278                              <1> _K504:
  2279                              <1> 	sti				
  2280                              <1> 	pop	esi			; RECOVER SI (esi)
  2281                              <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2282                              <1> %endif
  2283                              <1> 
  2284                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2285                              <1> _KIO_E_XLAT:
  2286 00000BE3 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2287 00000BE5 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2288 00000BE7 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2289 00000BE9 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2290 00000BEB 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2291                              <1> _KIO_E_RET:				
  2292 00000BED C3                  <1> 	retn				; GO BACK
  2293                              <1> 
  2294                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2295                              <1> _K1S:
  2296 00000BEE FA                  <1> 	cli	; 03/12/2014
  2297 00000BEF 8B1D[A05B0000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2298 00000BF5 3B1D[A45B0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2299                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2300 00000BFB 750F                <1> 	jne	short _k1x ; 03/12/2014
  2301                              <1> 	;
  2302                              <1> 	; 03/12/2014
  2303                              <1> 	; 28/08/2014
  2304                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2305                              <1> 	;;mov	ax, 9002h		; MOVE IN WAIT CODE & TYPE
  2306                              <1> 	;;int	15h			; PERFORM OTHER FUNCTION
  2307                              <1> _K1T:                                   ; ASCII READ
  2308 00000BFD FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2309 00000BFE 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2310                              <1> _K1U:	
  2311 00000BFF FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2312 00000C00 8B1D[A05B0000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2313 00000C06 3B1D[A45B0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2314                              <1> _k1x:
  2315 00000C0C 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2316 00000C0D 9C                  <1> 	pushf				; SAVE FLAGS
  2317 00000C0E E895060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2318 00000C13 8A1D[955B0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2319 00000C19 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2320 00000C1B 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2321 00000C1E 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2322 00000C20 E82F060000          <1> 	call	SND_LED1
  2323 00000C25 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2324                              <1> _K1V:
  2325 00000C26 9D                  <1> 	popf				; RESTORE FLAGS
  2326 00000C27 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2327 00000C28 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2328                              <1> 	;
  2329 00000C2A 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2330 00000C2D E834000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2331 00000C32 891D[A05B0000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2332 00000C38 C3                  <1> 	retn				; RETURN
  2333                              <1> 
  2334                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2335                              <1> _K2S:
  2336 00000C39 FA                  <1> 	cli				; INTERRUPTS OFF
  2337 00000C3A 8B1D[A05B0000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2338 00000C40 3B1D[A45B0000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2339 00000C46 668B03              <1> 	mov	ax, [ebx]
  2340 00000C49 9C                  <1> 	pushf				; SAVE FLAGS
  2341                              <1> 	;push	ax			; SAVE CODE
  2342                              <1> 	; 24/12/2021
  2343 00000C4A 50                  <1> 	push	eax
  2344 00000C4B E858060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2345 00000C50 8A1D[955B0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2346 00000C56 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2347 00000C58 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2348 00000C5B 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2349 00000C5D E8DB050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2350                              <1> _K2T:
  2351                              <1> 	;pop	ax			; RESTORE CODE
  2352                              <1> 	; 24/12/2021
  2353 00000C62 58                  <1> 	pop	eax
  2354 00000C63 9D                  <1> 	popf				; RESTORE FLAGS
  2355 00000C64 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2356 00000C65 C3                  <1> 	retn				; RETURN
  2357                              <1> 
  2358                              <1> 	; 24/07/2022
  2359                              <1> %if 0
  2360                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2361                              <1> _KIO_S_XLAT:
  2362                              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2363                              <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2364                              <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2365                              <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2366                              <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2367                              <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2368                              <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2369                              <1> _kio_ret: ; 03/12/2014
  2370                              <1> 	clc
  2371                              <1> 	retn
  2372                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2373                              <1> _KIO_S1:				
  2374                              <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2375                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2376                              <1> 	retn
  2377                              <1> _KIO_S2:		
  2378                              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2379                              <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2380                              <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2381                              <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2382                              <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2383                              <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2384                              <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2385                              <1> _KIO_S3:
  2386                              <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2387                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2388                              <1> 	jne	short _kio_ret
  2389                              <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2390                              <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2391                              <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2392                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2393                              <1> _KIO_USE:
  2394                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2395                              <1> 	retn				; RETURN	
  2396                              <1> _KIO_DIS:
  2397                              <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2398                              <1> 	retn				; RETURN
  2399                              <1> 
  2400                              <1> %endif
  2401                              <1> 
  2402                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2403                              <1> _K4:    
  2404 00000C66 43                  <1> 	inc     ebx
  2405 00000C67 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2406 00000C68 3B1D[9C5B0000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2407                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2408 00000C6E 7206                <1> 	jb	short _K5
  2409 00000C70 8B1D[985B0000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2410                              <1> _K5:
  2411 00000C76 C3                  <1> 	retn
  2412                              <1> 
  2413                              <1> ; 20/02/2015
  2414                              <1> ; 05/12/2014
  2415                              <1> ; 26/08/2014
  2416                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2417                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2418                              <1> ;
  2419                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2420                              <1> ; rombios source code (06/10/1985)
  2421                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2422                              <1> 
  2423                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2424                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2425                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2426                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2427                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2428                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2429                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2430                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2431                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2432                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2433                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2434                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2435                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2436                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2437                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2438                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2439                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2440                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2441                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2442                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2443                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2444                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2445                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2446                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2447                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2448                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2449                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2450                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2451                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2452                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2453                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2454                              <1> F11_M		equ	87		; F11 KEY MAKE
  2455                              <1> F12_M		equ	88		; F12 KEY MAKE
  2456                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2457                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2458                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2459                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2460                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2461                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2462                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2463                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2464                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2465                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2466                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2467                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2468                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2469                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2470                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2471                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2472                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2473                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2474                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2475                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2476                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2477                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2478                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2479                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2480                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2481                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2482                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2483                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2484                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2485                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2486                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2487                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2488                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2489                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2490                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2491                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2492                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2493                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2494                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2495                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2496                              <1> ;
  2497                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2498                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2499                              <1> INTA00		equ	020h		; 8259 PORT
  2500                              <1> 
  2501                              <1> kb_int:
  2502                              <1> 
  2503                              <1> ; 13/06/2022
  2504                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2505                              <1> ; 17/10/2015 ('ctrlbrk') 
  2506                              <1> ; 05/12/2014
  2507                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2508                              <1> ;	      instead of pc-at bios - 1985-)
  2509                              <1> ; 26/08/2014
  2510                              <1> ;
  2511                              <1> ; 03/06/86  KEYBOARD BIOS
  2512                              <1> ;
  2513                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2514                              <1> ;										;
  2515                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2516                              <1> ;										;
  2517                              <1> ;--------------------------------------------------------------------------------
  2518                              <1> 
  2519                              <1> KB_INT_1:
  2520 00000C77 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2521                              <1> 	;push	ebp
  2522 00000C78 50                  <1> 	push	eax
  2523 00000C79 53                  <1> 	push	ebx
  2524 00000C7A 51                  <1> 	push	ecx
  2525 00000C7B 52                  <1> 	push	edx
  2526 00000C7C 56                  <1> 	push	esi
  2527 00000C7D 57                  <1> 	push	edi
  2528 00000C7E 1E                  <1> 	push	ds
  2529 00000C7F 06                  <1> 	push	es
  2530 00000C80 FC                  <1> 	cld				; FORWARD DIRECTION
  2531 00000C81 66B81000            <1> 	mov	ax, KDATA
  2532 00000C85 8ED8                <1> 	mov	ds, ax
  2533 00000C87 8EC0                <1> 	mov	es, ax
  2534                              <1> 	;
  2535                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2536 00000C89 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2537 00000C8B E852050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2538 00000C90 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2539 00000C91 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2540                              <1> KB_INT_01:
  2541 00000C96 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2542 00000C98 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2543 00000C9A E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2544                              <1> 	;
  2545                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2546 00000C9C E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2547                              <1> 	;
  2548                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2549                              <1> 	;mov	ah, 04Fh		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2550                              <1> 	;stc				; SET CY=1 (IN CASE OF IRET)
  2551                              <1> 	;int	15h			; CASETTE CALL (AL)=KEY SCAN CODE
  2552                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2553                              <1> 	;jc	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2554                              <1> 	;jmp	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2555                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2556                              <1> 	;
  2557                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2558                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2559 00000C9E FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2560 00000C9F 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2561 00000CA1 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2562                              <1> 	;
  2563                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2564 00000CA3 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2565 00000CA5 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2566                              <1> 	;
  2567                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2568 00000CA7 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2569 00000CA8 800D[955B0000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2570 00000CAF E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2571                              <1> 	;
  2572                              <1> 	;-----	RESEND THE LAST BYTE
  2573                              <1> KB_INT_4:
  2574 00000CB4 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2575 00000CB5 800D[955B0000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2576 00000CBC E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2577                              <1> 	;
  2578                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2579                              <1> KB_INT_2:
  2580                              <1> 	;push 	ax			; SAVE DATA IN
  2581                              <1> 	; 24/12/2021
  2582 00000CC1 50                  <1> 	push	eax
  2583 00000CC2 E8E1050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2584 00000CC7 8A1D[955B0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2585 00000CCD 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2586 00000CCF 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2587 00000CD2 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2588 00000CD4 E864050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2589                              <1> UP0:
  2590                              <1> 	;pop	ax			; RESTORE DATA IN
  2591                              <1> 	; 24/12/2021
  2592 00000CD9 58                  <1> 	pop	eax
  2593                              <1> ;------------------------------------------------------------------------
  2594                              <1> ;	START OF KEY PROCESSING						;
  2595                              <1> ;------------------------------------------------------------------------
  2596 00000CDA 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2597                              <1> 	;
  2598                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2599 00000CDC 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2600                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2601                              <1> 	; 24/12/2021
  2602 00000CDE 7505                <1> 	jne	short K16
  2603 00000CE0 E9E9040000          <1> 	jmp	K62
  2604                              <1> K16:	
  2605 00000CE5 8A3D[965B0000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2606                              <1> 	;
  2607                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2608 00000CEB F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2609 00000CEE 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2610 00000CF0 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2611 00000CF2 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2612 00000CF4 7507                <1> 	jne	short RST_RD_ID
  2613 00000CF6 800D[965B0000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2614                              <1> RST_RD_ID:
  2615 00000CFD 8025[965B0000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2616 00000D04 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2617                              <1> 	; 24/12/2021
  2618                              <1> 	;jmp	K26
  2619                              <1> 	;
  2620                              <1> TST_ID_2:
  2621 00000D06 8025[965B0000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2622 00000D0D 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2623 00000D0F 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2624 00000D11 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2625 00000D13 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2626                              <1> 	; 24/12/2021
  2627                              <1> 	;jne	K26
  2628                              <1> 	;
  2629                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2630 00000D15 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2631 00000D18 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2632 00000D1A 800D[935B0000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2633 00000D21 E817050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2634                              <1> KX_BIT:
  2635 00000D26 800D[965B0000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2636 00000D2D E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2637                              <1> 	;
  2638                              <1> NOT_ID:
  2639 00000D32 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2640 00000D34 750E                <1> 	jne	short TEST_E1
  2641 00000D36 800D[965B0000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2642 00000D3D EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2643                              <1> 	; 24/12/2021
  2644 00000D3F E9DA010000          <1> 	jmp	K26A	
  2645                              <1> TEST_E1:	
  2646 00000D44 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2647 00000D46 750C                <1> 	jne	short NOT_HC
  2648 00000D48 800D[965B0000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2649 00000D4F E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2650                              <1> 	;
  2651                              <1> NOT_HC:
  2652 00000D54 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2653 00000D56 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2654 00000D59 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2655                              <1> 	;
  2656 00000D5B BF[7E5A0000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2657 00000D60 AE                  <1> 	scasb
  2658                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2659                              <1> 	; 24/12/2021
  2660 00000D61 7458                <1> 	je	short K16B
  2661 00000D63 AE                  <1> 	scasb
  2662 00000D64 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2663 00000D66 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2664                              <1> 	; 24/12/2021
  2665                              <1> 	;jmp	K26
  2666                              <1> 	;
  2667                              <1> NOT_LC_E0:
  2668 00000D68 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2669 00000D6B 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2670 00000D6D B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2671 00000D72 BF[7C5A0000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2672 00000D77 F2AE                <1> 	repne	scasb			; CHECK IT
  2673 00000D79 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2674                              <1> 	; 24/12/2021
  2675                              <1> 	;je	K26A			
  2676                              <1> 	;
  2677 00000D7B 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2678 00000D7D 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2679                              <1> 	; 24/12/2021
  2680                              <1> 	;jne	K26
  2681 00000D7F F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2682 00000D82 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2683                              <1> 	; 24/12/2021
  2684                              <1> 	;jnz	K26
  2685                              <1>         ; 20/02/2015 
  2686 00000D84 F605[945B0000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2687 00000D8B 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2688                              <1> 	; 24/12/2021
  2689                              <1> 	;jnz	K26
  2690 00000D8D E9D2020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2691                              <1> 	;
  2692                              <1> 	;-----	TEST FOR SYSTEM KEY
  2693                              <1> T_SYS_KEY:
  2694 00000D92 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2695 00000D94 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2696                              <1> 	;
  2697 00000D96 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2698 00000D99 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2699                              <1> 	;
  2700 00000D9B F605[945B0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2701 00000DA2 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2702                              <1> 	;jnz	K26			
  2703                              <1> 	;
  2704 00000DA4 800D[945B0000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2705 00000DAB B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2706 00000DAD E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2707                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2708 00000DAF B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2709 00000DB1 E82C040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2710                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2711                              <1> 	;mov	al, 8500h		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2712                              <1> 	;sti				; MAKE SURE INTERRUPTS ENABLED
  2713                              <1> 	;int	15h			; USER INTERRUPT	
  2714 00000DB6 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2715                              <1> 	;
  2716 00000DBB E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2717                              <1> 	;
  2718                              <1> K16C:
  2719 00000DC0 8025[945B0000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2720 00000DC7 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2721 00000DC9 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2722                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2723                              <1> 	;mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2724                              <1> 	;call	SHIP_IT			; EXECUTE ENABLE
  2725                              <1> 	;
  2726                              <1> 	;mov	ax, 8501h		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2727                              <1> 	;sti				; MAKE SURE INTERRUPTS ENABLED
  2728                              <1> 	;int	15h			; USER INTERRUPT
  2729                              <1> 	;jmp	K27A			; INGONRE SYSTEM KEY				
  2730                              <1> 	;
  2731 00000DCB E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2732                              <1> 	;
  2733                              <1> 	;-----	TEST FOR SHIFT KEYS
  2734                              <1> K16A:
  2735 00000DD0 8A1D[935B0000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2736 00000DD6 BF[785A0000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2737 00000DDB B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2738 00000DE0 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2739 00000DE2 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2740                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2741                              <1> 	; 24/12/2021
  2742 00000DE4 7405                <1> 	je	short K17
  2743 00000DE6 E914010000          <1> 	jmp	K25
  2744                              <1> 	;
  2745                              <1> 	;------	SHIFT KEY FOUND
  2746                              <1> K17:
  2747 00000DEB 81EF[795A0000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2748 00000DF1 8AA7[805A0000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2749 00000DF7 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2750 00000DF9 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2751                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2752                              <1> 	; 24/12/2021
  2753 00000DFB 7405                <1> 	jz	short K17C
  2754 00000DFD E999000000          <1> 	jmp	K23
  2755                              <1> 	;
  2756                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2757                              <1> K17C:
  2758 00000E02 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2759 00000E05 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2760                              <1> 	;
  2761                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2762 00000E07 0825[935B0000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2763 00000E0D A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2764 00000E0F 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2765                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2766                              <1> 	; 24/12/2021
  2767 00000E11 E901010000          <1> 	jmp	K26
  2768                              <1> K17D:
  2769 00000E16 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2770 00000E19 740B                <1> 	jz 	short K17E		; NO, JUMP
  2771 00000E1B 0825[965B0000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2772 00000E21 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2773                              <1> K17E:
  2774 00000E26 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2775 00000E28 0825[945B0000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2776 00000E2E E9E4000000          <1> 	jmp	K26
  2777                              <1> 	;
  2778                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2779                              <1> K18:					; SHIFT-TOGGLE
  2780 00000E33 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2781 00000E36 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2782                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2783                              <1> 	; 24/12/2021
  2784 00000E38 E9C2000000          <1> 	jmp	K25
  2785                              <1> K18A:
  2786 00000E3D 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2787 00000E3F 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2788 00000E41 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2789 00000E44 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2790                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2791                              <1> 	; 24/12/2021
  2792 00000E46 E9B4000000          <1> 	jmp	K25
  2793                              <1> K18B:
  2794 00000E4B F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2795 00000E4E 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2796                              <1> K19:	
  2797 00000E50 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2798 00000E53 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2799 00000E55 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2800 00000E58 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2801                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2802 00000E5A 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2803 00000E5C E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2804                              <1> K21:					; MIGHT BE NUMERIC
  2805 00000E61 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2806 00000E64 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2807                              <1> 	;
  2808                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2809 00000E66 8425[945B0000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2810                              <1> 	;jnz	K26
  2811                              <1> 	; 24/12/2021
  2812 00000E6C 7405                <1> 	jz	short K22A
  2813 00000E6E E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2814                              <1> K22A:
  2815 00000E73 0825[945B0000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2816 00000E79 3025[935B0000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2817                              <1> 	;
  2818                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2819 00000E7F F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2820 00000E82 7407                <1> 	jz	short K22B		; GO IF NOT
  2821                              <1> 	;
  2822                              <1> 	; 24/12/2021
  2823                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2824 00000E84 50                  <1> 	push	eax
  2825 00000E85 E8B3030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2826                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2827 00000E8A 58                  <1> 	pop	eax
  2828                              <1> K22B:
  2829 00000E8B 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2830                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2831                              <1> 	; 24/12/2021
  2832 00000E8D 7405                <1> 	je	short K22C
  2833 00000E8F E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2834                              <1> K22C:
  2835 00000E94 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2836 00000E96 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2837                              <1> 	;
  2838                              <1> 	;-----	BREAK SHIFT FOUND
  2839                              <1> K23:					; BREAK-SHIFT-FOUND
  2840 00000E9B 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2841 00000E9E F6D4                <1> 	not	ah			; INVERT MASK
  2842 00000EA0 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2843 00000EA2 2025[935B0000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2844 00000EA8 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2845 00000EAB 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2846                              <1> 	;
  2847 00000EAD F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2848 00000EB0 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2849 00000EB2 2025[965B0000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2850 00000EB8 EB08                <1> 	jmp	short K23B		; CONTINUE
  2851                              <1> K23A:
  2852 00000EBA D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2853 00000EBC 2025[945B0000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2854                              <1> K23B:
  2855 00000EC2 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2856 00000EC4 A0[965B0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2857 00000EC9 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2858 00000ECB 0A05[945B0000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2859 00000ED1 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2860 00000ED3 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2861 00000ED5 0805[935B0000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2862 00000EDB 88E0                <1> 	mov	al, ah
  2863                              <1> K23D:
  2864 00000EDD 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2865 00000EDF 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2866                              <1> 	;	
  2867                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2868 00000EE1 A0[975B0000]        <1> 	mov	al, [ALT_INPUT]
  2869 00000EE6 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2870 00000EE8 8825[975B0000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2871 00000EEE 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2872 00000EF0 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2873 00000EF2 E9B4020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2874                              <1> 	;
  2875                              <1> K24:					; BREAK-TOGGLE
  2876 00000EF7 2025[945B0000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2877 00000EFD EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2878                              <1> 	;
  2879                              <1> 	;-----	TEST FOR HOLD STATE
  2880                              <1> 					; AL, AH = SCAN CODE
  2881                              <1> K25:					; NO-SHIFT-FOUND
  2882 00000EFF 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2883 00000F01 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2884 00000F03 F605[945B0000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2885 00000F0A 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2886 00000F0C 3C45                <1> 	cmp	al, NUM_KEY
  2887 00000F0E 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2888 00000F10 8025[945B0000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2889                              <1> 	;
  2890                              <1> K26:
  2891 00000F17 8025[965B0000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2892                              <1> K26A:					; INTERRUPT-RETURN
  2893 00000F1E FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2894 00000F1F B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2895 00000F21 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2896                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2897 00000F23 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2898 00000F25 E8B8020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2899                              <1> K27A:
  2900 00000F2A FA                  <1> 	cli				; DISABLE INTERRUPTS
  2901 00000F2B 07                  <1> 	pop	es			; RESTORE REGISTERS
  2902 00000F2C 1F                  <1> 	pop	ds
  2903 00000F2D 5F                  <1> 	pop	edi
  2904 00000F2E 5E                  <1> 	pop	esi
  2905 00000F2F 5A                  <1> 	pop	edx
  2906 00000F30 59                  <1> 	pop	ecx
  2907 00000F31 5B                  <1> 	pop	ebx
  2908 00000F32 58                  <1> 	pop	eax
  2909                              <1> 	;pop	ebp
  2910 00000F33 CF                  <1> 	iret				; RETURN
  2911                              <1> 
  2912                              <1> 	;-----	NOT IN	HOLD STATE
  2913                              <1> K28:					; NO-HOLD-STATE
  2914 00000F34 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2915 00000F36 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2916                              <1> 	;
  2917 00000F38 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2918 00000F3B 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2919                              <1>         ; 24/12/2021
  2920                              <1> 	;jz	K38
  2921                              <1> 	;
  2922 00000F3D F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2923 00000F40 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2924                              <1> 	; 28/02/2015
  2925 00000F42 F605[945B0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2926 00000F49 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2927                              <1> 	; 24/12/2021
  2928                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2929                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2930 00000F4B E9CD000000          <1> K28A:	jmp	K38
  2931                              <1> 	;
  2932                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2933                              <1> K29:					; TEST-RESET
  2934 00000F50 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2935 00000F53 740B                <1> 	jz	short K31		; NO_RESET
  2936 00000F55 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2937 00000F57 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2938                              <1> 	;
  2939                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2940                              <1>  	; 26/08/2014
  2941                              <1> cpu_reset:
  2942                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2943                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2944 00000F59 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2945 00000F5B E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2946                              <1> khere:
  2947 00000F5D F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2948 00000F5E EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2949                              <1> 
  2950                              <1> 	;
  2951                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2952                              <1> K31:					; NO-RESET
  2953 00000F60 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2954 00000F62 7507                <1> 	jne	short K311		; NOT THERE
  2955 00000F64 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2956 00000F66 E932020000          <1>         jmp     K57                     ; BUFFER_FILL
  2957                              <1> K311:
  2958 00000F6B 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2959 00000F6D 7509                <1> 	jne	short K312		; NOT THERE
  2960 00000F6F 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2961 00000F73 E925020000          <1>         jmp     K57                     ; BUFFER_FILL
  2962                              <1> K312:
  2963 00000F78 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2964 00000F7A 7471                <1>         je	short K37B              ; GO PROCESS
  2965 00000F7C 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2966 00000F7E 746D                <1>         je	short K37B              ; GO PROCESS
  2967                              <1> 	;
  2968                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2969                              <1> K32:					; ALT-KEY-PAD
  2970 00000F80 BF[545A0000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2971 00000F85 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2972 00000F8A F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2973 00000F8C 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2974 00000F8E F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2975                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2976                              <1> 	; 24/12/2021
  2977 00000F91 751C                <1> 	jnz	short K32B
  2978 00000F93 81EF[555A0000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2979 00000F99 A0[975B0000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2980 00000F9E B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2981 00000FA0 F6E4                <1> 	mul	ah
  2982 00000FA2 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2983 00000FA5 A2[975B0000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2984                              <1> K32A:
  2985 00000FAA E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2986                              <1> K32B:
  2987                              <1> 	; 24/12/2021
  2988 00000FAF EB66                <1> 	jmp	K37C
  2989                              <1> 	;
  2990                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2991                              <1> K33:					; NO-ALT-KEYPAD
  2992 00000FB1 C605[975B0000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2993 00000FB8 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2994 00000FBD F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2995 00000FBF 744F                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2996                              <1> 	;
  2997                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2998                              <1> K34:					; ALT-TOP-ROW
  2999 00000FC1 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  3000 00000FC3 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  3001 00000FC5 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  3002 00000FC7 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  3003 00000FC9 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  3004 00000FCC EB42                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  3005                              <1> 	;
  3006                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  3007                              <1> K35:					; ALT-FUNCTION
  3008 00000FCE 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  3009 00000FD0 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  3010 00000FD2 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  3011 00000FD4 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  3012 00000FD6 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  3013 00000FD9 EB35                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  3014                              <1> K35A:
  3015 00000FDB F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  3016 00000FDE 7425                <1> 	jz	short K37		; NO, JUMP
  3017 00000FE0 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  3018 00000FE2 7510                <1>         jne     short K35B              ; NOT THERE
  3019 00000FE4 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  3020 00000FE8 E9B0010000          <1> 	jmp	K57			; BUFFER FILL
  3021                              <1> K37B:
  3022 00000FED B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  3023 00000FEF E9A9010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  3024                              <1> K35B:
  3025 00000FF4 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3026 00000FF6 741F                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3027 00000FF8 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3028 00000FFA 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3029                              <1>         ; 24/12/2021
  3030                              <1> 	;jne	K26
  3031 00000FFC 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3032 00001000 E998010000          <1> 	jmp	K57			; BUFFER FILL
  3033                              <1> K37:
  3034 00001005 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3035 00001007 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3036 00001009 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3037 0000100B 779D                <1>         ja	short K32A		; IF SO, IGNORE
  3038                              <1> 	; 13/06/2022
  3039                              <1>         ;ja	K26
  3040 0000100D 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3041                              <1> K37A:
  3042 00001010 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3043 00001012 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3044                              <1> K37C:
  3045 00001017 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3046 00001019 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3047 0000101B EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3048                              <1> 	;
  3049                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3050                              <1> K38:					; NOT-ALT-SHIFT
  3051                              <1> 					; BL STILL HAS SHIFT FLAGS
  3052 0000101D F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3053 00001020 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3054                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3055                              <1> 	; 24/12/2021
  3056 00001022 E9AB000000          <1> 	jmp	K44
  3057                              <1> 	;
  3058                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3059                              <1> 	;-----	TEST FOR BREAK
  3060                              <1> K38A:
  3061 00001027 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3062 00001029 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3063 0000102B F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3064 0000102E 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3065 00001030 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3066 00001033 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3067                              <1> K38B:
  3068 00001035 8B1D[A05B0000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3069 0000103B 891D[A45B0000]      <1> 	mov	[BUFFER_TAIL], ebx
  3070 00001041 C605[925B0000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3071                              <1> 	;
  3072                              <1> 	;-----	ENABLE KEYBOARD
  3073 00001048 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3074 0000104A E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3075                              <1> 	;
  3076                              <1> 	; CTRL+BREAK code here !!!
  3077                              <1> 	;int	1Bh			; BREAK INTERRUPT VECTOR
  3078                              <1> 	; 17/10/2015	
  3079 0000104F E889190000          <1> 	call	ctrlbrk ; control+break subroutine
  3080                              <1> 	;
  3081                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3082                              <1> 	; 24/12/2021
  3083 00001054 29C0                <1> 	sub	eax, eax
  3084 00001056 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3085                              <1> 	;
  3086                              <1> 	;-----	TEST FOR PAUSE
  3087                              <1> K39:					; NO_BREAK
  3088 0000105B F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3089 0000105E 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3090 00001060 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3091 00001062 7533                <1> 	jne	short K41		; NO-PAUSE
  3092                              <1> K39P:
  3093 00001064 800D[945B0000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3094                              <1> 	;
  3095                              <1> 	;-----	ENABLE KEYBOARD
  3096 0000106B B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3097 0000106D E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3098                              <1> K39A:
  3099 00001072 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3100 00001074 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3101                              <1> 	;
  3102                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3103 00001076 803D[905B0000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3104 0000107D 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3105 0000107F 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3106 00001083 A0[915B0000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3107 00001088 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3108                              <1> 	;
  3109                              <1> K40:					; PAUSE-LOOP
  3110 00001089 F605[945B0000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3111 00001090 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3112                              <1> 	;
  3113 00001092 E98CFEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3114                              <1>         ;
  3115                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3116                              <1> K41:					; NO-PAUSE
  3117 00001097 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3118 00001099 7513                <1> 	jne	short K42		; NOT-KEY-55
  3119 0000109B F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3120 0000109E 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3121 000010A0 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3122 000010A3 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3123                              <1> K41A:	
  3124 000010A5 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3125 000010A9 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3126                              <1> 	;
  3127                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3128                              <1> K42:					; NOT-KEY-55
  3129 000010AE 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3130 000010B0 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3131 000010B2 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3132 000010B4 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3133 000010B6 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3134 000010B9 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3135 000010BB 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3136 000010BF E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3137                              <1> K42A:
  3138                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3139 000010C4 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3140                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3141                              <1> 	;;jb	K56 ; 20/02/2015
  3142                              <1> 	;;jmp	K64 ; 20/02/2015
  3143                              <1> K42B:
  3144 000010C6 BB[885A0000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3145                              <1> 	;;jmp	K64
  3146                              <1> 	;jb	K56 ;; 20/02/2015	
  3147                              <1> 	; 24/12/2021
  3148 000010CB 7267                <1> 	jb	short K45F
  3149 000010CD E9B9000000          <1> 	jmp	K64	
  3150                              <1>         ;
  3151                              <1> 	;-----	NOT IN CONTROL SHIFT
  3152                              <1> K44:					; NOT-CTL-SHIFT
  3153 000010D2 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3154 000010D4 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3155 000010D6 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3156 000010D9 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3157 000010DB F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3158 000010DE 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3159 000010E0 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3160                              <1> K44A:
  3161 000010E2 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3162 000010E5 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3163                              <1> 	;
  3164                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3165                              <1> K44B:
  3166 000010E7 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3167 000010E9 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3168 000010EE B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3169 000010F0 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3170                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3171                              <1> 	;push	bp			; SAVE POINTER
  3172                              <1> 	;int	05h			; ISSUE PRINT SCREEN INTERRUPT
  3173                              <1> 	;pop	bp			; RESTORE POINTER
  3174 000010F2 8025[965B0000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3175 000010F9 E925FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3176                              <1> 	;
  3177                              <1> 	;-----	HANDLE IN-CORE KEYS
  3178                              <1> K45:					; NOT-PRINT-SCREEN
  3179 000010FE 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3180 00001100 7734                <1> 	ja	short K46		; JUMP IF NOT
  3181 00001102 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3182 00001104 7505                <1> 	jne	short K45A		; NO, JUMP
  3183 00001106 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3184 00001109 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3185                              <1> K45A:
  3186 0000110B B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3187 00001110 BF[5E5A0000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3188 00001115 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3189                              <1> 		; 20/02/2015
  3190 00001117 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3191                              <1> 	;
  3192 00001119 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3193 0000111C 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3194                              <1> K45B:
  3195 0000111E F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3196 00001121 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3197                              <1> 					; NO, LOWERCASE
  3198                              <1> K45C:
  3199 00001123 BB[E05A0000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3200 00001128 EB51                <1> 	jmp	short K56	
  3201                              <1> K45D:					; ALMOST-CAPS-STATE
  3202 0000112A F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3203 0000112D 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3204                              <1> K45E:
  3205 0000112F BB[385B0000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3206 00001134 EB45                <1> K45F:	jmp	short K56
  3207                              <1> 	;
  3208                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3209                              <1> K46:					; NOT IN-CORE AREA
  3210 00001136 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3211                              <1> 	;ja	short K47		; JUMP IF NOT
  3212                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3213 00001138 7635                <1> 	jna	short K53		
  3214                              <1> 	;
  3215                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3216                              <1> K47:					; NOT F1 - F10
  3217 0000113A 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3218 0000113C 772D                <1> 	ja	short K52		; JUMP IF NOT
  3219                              <1> 	;
  3220                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3221                              <1> K48:
  3222 0000113E 3C4A                <1> 	cmp	al, 74			; SPECIAL CASE FOR MINUS
  3223 00001140 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3224 00001142 3C4E                <1> 	cmp	al, 78			; SPECIAL CASE FOR PLUS
  3225 00001144 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3226 00001146 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3227 00001149 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3228                              <1> 	;		
  3229 0000114B F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3230 0000114E 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3231 00001150 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3232                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3233 00001153 75DA                <1> 	jnz	short K45E
  3234                              <1> 	;
  3235                              <1> 	;-----	BASE CASE FOR KEYPAD
  3236                              <1> K49:					
  3237 00001155 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3238 00001157 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3239 00001159 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3240 0000115B EB40                <1> 	jmp	short K57		; BUFFER FILL
  3241                              <1> K49A:
  3242 0000115D BB[E05A0000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3243 00001162 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3244                              <1> 	;
  3245                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3246                              <1> K50:					; ALMOST-NUM-STATE
  3247 00001164 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3248 00001167 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3249 00001169 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3250                              <1> 	;
  3251                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3252                              <1> K52:					; NOT A NUMPAD KEY
  3253 0000116B 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3254                              <1> 	;jne	short K53		; JUMP IF NOT
  3255                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3256 0000116D 74AF                <1> 	je	short K45B		
  3257                              <1> 	;
  3258                              <1> 	;-----	MUST BE F11 OR F12 
  3259                              <1> K53:					; F1 - F10 COME HERE, TOO
  3260 0000116F F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3261 00001172 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3262                              <1> 		; 20/02/2015 
  3263 00001174 BB[385B0000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3264 00001179 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3265                              <1> 	;
  3266                              <1> 	;-----	TRANSLATE THE CHARACTER
  3267                              <1> K56:					; TRANSLATE-CHAR
  3268 0000117B FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3269 0000117D D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3270 0000117E F605[965B0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3271 00001185 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3272 00001187 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3273 00001189 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3274                              <1> 	;
  3275                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3276                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3277 0000118B FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3278 0000118D D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3279 0000118E 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3280 00001190 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3281 00001192 F605[965B0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3282 00001199 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3283 0000119B B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3284                              <1> 	;
  3285                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3286                              <1> K57:					; BUFFER_FILL
  3287 0000119D 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3288 0000119F 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3289                              <1> 	; 24/12/2021
  3290                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3291 000011A1 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3292                              <1> 	; 24/12/2021
  3293 000011A4 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3294                              <1> 	;je	K26			; INTERRUPT_RETURN
  3295                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3296 000011A6 E96CFDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3297                              <1> K61:					; NOT-CAPS-STATE
  3298 000011AB 8B1D[A45B0000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3299 000011B1 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3300 000011B3 E8AEFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3301 000011B8 3B1D[A05B0000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3302 000011BE 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3303 000011C0 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3304 000011C3 891D[A45B0000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3305 000011C9 E949FDFFFF          <1> 	jmp	K26
  3306                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3307                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3308                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3309                              <1> 	;mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3310                              <1> 	;call	SHIP_IT			; EXECUTE ENABLE
  3311                              <1> 	;mov	ax, 9102h		; MOVE IN POST CODE & TYPE
  3312                              <1> 	;int	15h			; PERFORM OTHER FUNCTION
  3313                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3314                              <1> 	;jmp	K27A			; INTERRUPT_RETURN
  3315                              <1> 	;;jmp   K27                    
  3316                              <1> 	;
  3317                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3318                              <1> K62:
  3319 000011CE B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3320 000011D0 E620                <1> 	out	INTA00, al
  3321 000011D2 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3322 000011D6 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3323 000011D8 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3324 000011DD E941FDFFFF          <1> 	jmp     K27			; EXIT   
  3325                              <1> 
  3326                              <1> SHIP_IT:
  3327                              <1> 	;---------------------------------------------------------------------------------
  3328                              <1> 	; SHIP_IT
  3329                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3330                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3331                              <1> 	;---------------------------------------------------------------------------------
  3332                              <1> 	;
  3333                              <1> 	;push	ax			; SAVE DATA TO SEND
  3334                              <1> 	; 24/12/2021
  3335 000011E2 50                  <1> 	push	eax
  3336                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3337 000011E3 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3338                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3339 000011E4 B900000100          <1> 	mov	ecx, 10000h			
  3340                              <1> S10:
  3341 000011E9 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3342 000011EB A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3343 000011ED E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3344                              <1> 
  3345                              <1> 	;pop	ax			; GET DATA TO SEND
  3346                              <1> 	; 24/12/2021
  3347 000011EF 58                  <1> 	pop	eax
  3348 000011F0 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3349 000011F2 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3350 000011F3 C3                  <1> 	retn				; RETURN TO CALLER
  3351                              <1> 
  3352                              <1> SND_DATA:
  3353                              <1> 	; ---------------------------------------------------------------------------------
  3354                              <1> 	; SND_DATA
  3355                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3356                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3357                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3358                              <1> 	; ---------------------------------------------------------------------------------
  3359                              <1> 	;
  3360                              <1> 	;push	ax			; SAVE REGISTERS
  3361                              <1> 	;push	bx
  3362                              <1> 	; 24/12/2021
  3363 000011F4 50                  <1> 	push	eax
  3364 000011F5 53                  <1> 	push	ebx
  3365 000011F6 51                  <1> 	push	ecx
  3366 000011F7 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3367 000011F9 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3368                              <1> SD0:
  3369 000011FB FA                  <1> 	cli				; DISABLE INTERRUPTS
  3370 000011FC 8025[955B0000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3371                              <1> 	;
  3372                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3373 00001203 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3374                              <1> SD5:
  3375 00001208 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3376 0000120A A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3377 0000120C E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3378                              <1> 	;
  3379 0000120E 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3380 00001210 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3381 00001212 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3382                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3383 00001213 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3384                              <1> SD1:
  3385 00001218 F605[955B0000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3386 0000121F 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3387 00001221 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3388                              <1> SD2:
  3389 00001223 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3390 00001225 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3391 00001227 800D[955B0000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3392 0000122E EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3393                              <1> SD3:
  3394 00001230 F605[955B0000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3395 00001237 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3396                              <1> SD4:	
  3397 00001239 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3398                              <1> 	;pop	bx
  3399                              <1> 	;pop	ax
  3400                              <1> 	; 24/12/2021
  3401 0000123A 5B                  <1> 	pop	ebx
  3402 0000123B 58                  <1> 	pop	eax
  3403 0000123C C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3404                              <1> 
  3405                              <1> SND_LED:
  3406                              <1> 	; ---------------------------------------------------------------------------------
  3407                              <1> 	; SND_LED
  3408                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3409                              <1> 	;
  3410                              <1> 	;----------------------------------------------------------------------------------
  3411                              <1> 	;
  3412 0000123D FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3413 0000123E F605[955B0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3414 00001245 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3415                              <1> 	;
  3416 00001247 800D[955B0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3417 0000124E B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3418 00001250 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3419 00001252 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3420                              <1> SND_LED1:
  3421 00001254 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3422 00001255 F605[955B0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3423 0000125C 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3424                              <1> 	;
  3425 0000125E 800D[955B0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3426                              <1> SL0:
  3427 00001265 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3428 00001267 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3429 0000126C FA                  <1> 	cli
  3430 0000126D E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3431 00001272 8025[955B0000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3432 00001279 0805[955B0000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3433 0000127F F605[955B0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3434 00001286 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3435                              <1> 	;
  3436 00001288 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3437 0000128D FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3438 0000128E F605[955B0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3439 00001295 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3440                              <1> SL2:
  3441 00001297 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3442 00001299 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3443 0000129E FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3444                              <1> SL3:
  3445 0000129F 8025[955B0000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3446                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3447 000012A6 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3448 000012A7 C3                  <1> 	retn				; RETURN TO CALLER
  3449                              <1> 
  3450                              <1> MAKE_LED:
  3451                              <1> 	;---------------------------------------------------------------------------------
  3452                              <1> 	; MAKE_LED
  3453                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3454                              <1> 	;	THE MODE INDICATORS.
  3455                              <1> 	;---------------------------------------------------------------------------------
  3456                              <1> 	;
  3457                              <1> 	;push 	cx			; SAVE CX
  3458 000012A8 A0[935B0000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3459 000012AD 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3460                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3461                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3462 000012AF C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3463 000012B2 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3464                              <1> 	;pop	cx
  3465 000012B4 C3                  <1> 	retn				; RETURN TO CALLER
  3466                              <1> 
  3467                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3468                              <1> 
  3469                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1834                                  
  1835                                  %include 'video.inc' ; 07/03/2015
  1836                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - VIDEO.INC
  1837                              <1> ; Last Modification: 14/06/2022
  1838                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1839                              <1> ;
  1840                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1841                              <1> 
  1842                              <1> ; 14/06/2022
  1843                              <1> ; 25/02/2022
  1844                              <1> ; 02/02/2022 (simplified scroll up)
  1845                              <1> ; 16/01/2016
  1846                              <1> ; 30/06/2015
  1847                              <1> ; 27/06/2015
  1848                              <1> ; 11/03/2015
  1849                              <1> ; 02/09/2014
  1850                              <1> ; 30/08/2014
  1851                              <1> ; VIDEO FUNCTIONS
  1852                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1853                              <1> 
  1854                              <1> write_tty:
  1855                              <1> 	; 02/02/2022
  1856                              <1> 	; 13/08/2015
  1857                              <1> 	; 02/09/2014
  1858                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1859                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1860                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1861                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1862                              <1> 	;
  1863                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1864                              <1> 	;	   AL = Character to be written
  1865                              <1> 	;	   EBX = Video Page (0 to 7)
  1866                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1867                              <1> 
  1868                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1869                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1870                              <1> 
  1871                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1872                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1873                              <1> ;
  1874                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1875                              <1> ;
  1876                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1877                              <1> ;										:
  1878                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1879                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1880                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1881                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1882                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1883                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1884                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1885                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1886                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1887                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1888                              <1> ;   THE 0 COLOR IS USED.							:
  1889                              <1> ;   ENTRY --									:
  1890                              <1> ;     (AH) = CURRENT CRT MODE							:
  1891                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1892                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1893                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1894                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1895                              <1> ;   EXIT -- 									:
  1896                              <1> ;     ALL REGISTERS SAVED							:
  1897                              <1> ;--------------------------------------------------------------------------------
  1898                              <1> 
  1899 000012B5 FA                  <1> 	cli
  1900                              <1> 	;
  1901                              <1> 	; READ CURSOR (04/12/2013)
  1902                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1903 000012B6 08FF                <1> 	or	bh, bh
  1904                              <1> 	;jnz	beeper
  1905                              <1> 	; 02/02/2022
  1906 000012B8 7405                <1> 	jz	short u14
  1907 000012BA E992000000          <1> 	jmp	beeper
  1908                              <1> u14:
  1909                              <1> 	; 02/02/2022
  1910                              <1> 	;; 01/09/2014
  1911                              <1> 	;cmp	byte [CRT_MODE], 3
  1912                              <1> 	;je	short m3
  1913                              <1> 	;;
  1914                              <1> 	;call	set_mode
  1915                              <1> m3:
  1916 000012BF 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1917                              <1> 	;shl	si, 1
  1918                              <1> 	; 02/02/2022
  1919 000012C1 D1E6                <1> 	shl	esi, 1
  1920 000012C3 81C6[56610000]      <1> 	add	esi, cursor_posn
  1921 000012C9 668B16              <1> 	mov	dx, [esi]
  1922                              <1> 	;
  1923                              <1> 	; dx now has the current cursor position
  1924                              <1> 	;
  1925 000012CC 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1926 000012CE 7647                <1> 	jbe	short u8
  1927                              <1> 	;
  1928                              <1> 	; write the char to the screen
  1929                              <1> u0:	
  1930                              <1> 	; ah = attribute/color
  1931                              <1> 	; al = character
  1932                              <1> 	; bl = video page number (0 to 7)
  1933                              <1> 	; bh = 0
  1934                              <1> 	;
  1935 000012D0 E8D2010000          <1> 	call	write_c_current
  1936                              <1> 	;
  1937                              <1> 	; position the cursor for next char
  1938 000012D5 FEC2                <1> 	inc	dl		; next column
  1939                              <1> 	;cmp	dl, [CRT_COLS]
  1940 000012D7 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1941                              <1>         ;jne	set_cpos
  1942                              <1> 	; 02/02/2022
  1943 000012DA 7405                <1> 	je	short u13
  1944 000012DC E9DE000000          <1> 	jmp	set_cpos
  1945                              <1> u13:
  1946 000012E1 B200                <1> 	mov	dl, 0		; column = 0
  1947                              <1> u10:				; (line feed found)
  1948 000012E3 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1949 000012E6 7228                <1> 	jb 	short u6
  1950                              <1> 	;
  1951                              <1> 	; scroll required
  1952                              <1> u1:	
  1953                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1954 000012E8 E8D2000000          <1> 	call	set_cpos
  1955                              <1> 	;
  1956                              <1> 	; determine value to fill with during scroll
  1957                              <1> u2:
  1958                              <1> 	; READ_AC_CURRENT		:
  1959                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1960                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1961                              <1> 	;
  1962                              <1> 	; INPUT				
  1963                              <1> 	;	(AH) = CURRENT CRT MODE
  1964                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1965                              <1> 	;	(DS) = DATA SEGMENT
  1966                              <1> 	;	(ES) = REGEN SEGMENT
  1967                              <1> 	; OUTPUT			
  1968                              <1> 	;	(AL) = CHARACTER READ
  1969                              <1> 	;	(AH) = ATTRIBUTE READ
  1970                              <1> 	;
  1971                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1972                              <1> 	;
  1973                              <1> 	; bl = video page number
  1974                              <1> 	;
  1975 000012ED E829010000          <1> 	call	find_position	; get regen location and port address
  1976                              <1> 	; dx = status port
  1977                              <1> 	; esi = cursor location/address
  1978                              <1> p11:
  1979 000012F2 FB                  <1> 	sti			; enable interrupts
  1980 000012F3 90                  <1> 	nop			; allow for small interupts window
  1981 000012F4 FA                  <1> 	cli			; blocks interrupts for single loop
  1982 000012F5 EC                  <1> 	in	al, dx		; get status from adapter
  1983 000012F6 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1984 000012F8 75F8                <1> 	jnz	short p11	; wait until it is
  1985                              <1> p12:				; now wait for either retrace high
  1986 000012FA EC                  <1> 	in	al, dx		; get status
  1987 000012FB A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1988 000012FD 74FB                <1> 	jz	short p12	; wait until either is active	
  1989                              <1> p13:
  1990 000012FF 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1991 00001305 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  1992                              <1> 	;
  1993                              <1> 	; al = character, ah = attribute
  1994                              <1> 	;
  1995 00001308 FB                  <1> 	sti
  1996                              <1> 	; bl = video page number 	
  1997                              <1> u3:
  1998                              <1> 	;;mov	ax, 0601h 	; scroll one line
  1999                              <1> 	;;sub	cx, cx		; upper left corner
  2000                              <1> 	;;mov	dh, 25-1 	; lower right row
  2001                              <1> 	;;;mov	dl, [CRT_COLS]
  2002                              <1> 	;mov	dl, 80		; lower right column	
  2003                              <1> 	;;dec	dl
  2004                              <1> 	;;mov	dl, 79
  2005                              <1> 
  2006                              <1> 	;;call	scroll_up	; 04/12/2013
  2007                              <1> 	;;; 11/03/2015
  2008                              <1> 	; 02/09/2014
  2009                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2010                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2011                              <1> 	; 11/03/2015
  2012                              <1> 	;sub	cx, cx
  2013                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2014                              <1> 	;
  2015                              <1> 	; 02/02/2022 (simplied scroll up)
  2016                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2017                              <1> 	;
  2018 00001309 B001                <1> 	mov	al, 1		; scroll 1 line up
  2019                              <1> 		; ah = attribute
  2020 0000130B E935010000          <1> 	jmp	scroll_up
  2021                              <1> ;u4:
  2022                              <1> 	;;int	10h		; video-call return
  2023                              <1> 				; scroll up the screen
  2024                              <1> 				; tty return
  2025                              <1> ;u5:
  2026                              <1> 	;retn			; return to the caller
  2027                              <1> 
  2028                              <1> u6:				; set-cursor-inc
  2029 00001310 FEC6                <1> 	inc	dh		; next row
  2030                              <1> 				; set cursor
  2031                              <1> ;u7:					
  2032                              <1> 	;;mov	ah, 02h
  2033                              <1> 	;;jmp	short u4 	; establish the new cursor
  2034                              <1> 	;call	set_cpos
  2035                              <1> 	;jmp 	short u5
  2036 00001312 E9A8000000          <1> 	jmp     set_cpos
  2037                              <1> 
  2038                              <1> 	; check for control characters
  2039                              <1> u8:
  2040 00001317 7434                <1> 	je	short u9
  2041 00001319 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2042 0000131B 74C6                <1> 	je	short u10
  2043 0000131D 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2044 0000131F 7430                <1> 	je	short u11
  2045 00001321 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2046                              <1> 	;jne	short u0
  2047 00001323 7420                <1> 	je	short bs	; 12/12/2013
  2048                              <1> 	; 12/12/2013 (tab stop)
  2049 00001325 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2050 00001327 75A7                <1> 	jne	short u0
  2051 00001329 88D0                <1> 	mov	al, dl
  2052 0000132B 6698                <1> 	cbw
  2053 0000132D B108                <1> 	mov	cl, 8
  2054 0000132F F6F1                <1> 	div	cl
  2055 00001331 28E1                <1> 	sub	cl, ah
  2056                              <1> ts:
  2057                              <1> 	; 02/09/2014
  2058                              <1> 	; 01/09/2014
  2059 00001333 B020                <1> 	mov	al, 20h
  2060                              <1> tsloop:
  2061                              <1> 	;push	cx
  2062                              <1> 	;push	ax
  2063                              <1> 	; 02/02/2022
  2064 00001335 51                  <1> 	push	ecx
  2065 00001336 50                  <1> 	push	eax
  2066 00001337 30FF                <1> 	xor 	bh, bh
  2067                              <1> 	;mov	bl, [active_page]
  2068 00001339 E881FFFFFF          <1> 	call	m3
  2069                              <1> 	; 02/02/2022
  2070 0000133E 58                  <1> 	pop	eax
  2071 0000133F 59                  <1>  	pop	ecx
  2072                              <1> 	;pop	ax  ; ah = attribute/color
  2073                              <1> 	;pop	cx
  2074 00001340 FEC9                <1> 	dec	cl
  2075 00001342 75F1                <1> 	jnz	short tsloop
  2076 00001344 C3                  <1> 	retn
  2077                              <1> bs:	
  2078                              <1> 	; back space found
  2079 00001345 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2080                              <1> 	;je	short u7 	; set_cursor
  2081 00001347 7476                <1> 	jz	short set_cpos
  2082                              <1> 	;dec	dx     		; no -- just move it back
  2083                              <1> 	; 02/02/2022
  2084 00001349 FECA                <1> 	dec	dl
  2085                              <1> 	;jmp	short u7
  2086 0000134B EB72                <1> 	jmp	short set_cpos
  2087                              <1> 
  2088                              <1> 	; carriage return found
  2089                              <1> u9:
  2090 0000134D B200                <1> 	mov	dl, 0 		; move to first column
  2091                              <1> 	;jmp	short u7
  2092 0000134F EB6E                <1> 	jmp	short set_cpos
  2093                              <1> 
  2094                              <1> 	; line feed found
  2095                              <1> ;u10:
  2096                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2097                              <1> ;	jne	short u6 	; no, just set the cursor
  2098                              <1> ;       jmp     u1              ; yes, scroll the screen
  2099                              <1> 
  2100                              <1> beeper: 
  2101                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2102                              <1> 	; 18/01/2014
  2103                              <1> 	; 03/12/2013
  2104                              <1> 	; bell found
  2105                              <1> u11:
  2106 00001351 FB                  <1> 	sti
  2107 00001352 3A1D[66610000]      <1> 	cmp	bl, [active_page]
  2108 00001358 7551                <1> 	jne	short u12	; Do not sound the beep 
  2109                              <1> 				; if it is not written on the active page
  2110 0000135A 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2111 0000135E B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2112                              <1> 	;call	beep		; sound the pod bell
  2113                              <1> 	;jmp	short u5 	; tty_return
  2114                              <1> 	;retn
  2115                              <1> 	
  2116                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2117                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2118                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2119                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2120                              <1> 
  2121                              <1> beep:
  2122                              <1> 	; 07/02/2015
  2123                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2124                              <1> 	; 18/01/2014
  2125                              <1> 	; 03/12/2013
  2126                              <1> 	;
  2127                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2128                              <1> 	;
  2129                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2130                              <1> 	;
  2131                              <1> 	; ENTRY:
  2132                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2133                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2134                              <1> 	; EXIT:			:
  2135                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2136                              <1> 
  2137 00001360 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2138 00001361 FA                  <1> 	cli			; block interrupts during update
  2139 00001362 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2140 00001364 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2141 00001366 EB00                <1> 	jmp	$+2		; I/O delay
  2142 00001368 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2143 0000136A E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2144 0000136C EB00                <1> 	jmp	$+2		; I/O delay
  2145 0000136E 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2146 00001370 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2147 00001372 E461                <1> 	in	al, PORT_B	; get current setting of port
  2148 00001374 88C4                <1> 	mov	ah, al		; save that setting
  2149 00001376 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2150 00001378 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2151                              <1> 	;popf	; 18/01/2014
  2152 0000137A FB                  <1> 	sti
  2153                              <1> g7:				; 1/64 second per count (bl)
  2154 0000137B B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2155 00001380 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2156 00001385 FECB                <1> 	dec	bl		; (bl) length count expired?
  2157 00001387 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2158                              <1> 	;
  2159                              <1> 	;pushf			; save interrupt status
  2160 00001389 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2161 0000138A E461                <1> 	in	al, PORT_B	; get current port value
  2162                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2163 0000138C 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2164 0000138E 20C4                <1>         and	ah, al		; someone turned them off during beep
  2165 00001390 88E0                <1> 	mov	al, ah		; recover value of port
  2166                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2167 00001392 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2168 00001394 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2169                              <1> 	;popf			; restore interrupt flag state
  2170 00001396 FB                  <1> 	sti
  2171 00001397 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2172 0000139C E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2173                              <1> 	;pushf			; save interrupt status
  2174 000013A1 FA                  <1> 	cli			; block interrupts during update
  2175 000013A2 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2176 000013A4 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2177 000013A6 08E0                <1> 	or	al, ah		; recover value of port_b
  2178 000013A8 E661                <1> 	out	PORT_B, al	; restore speaker status
  2179 000013AA 9D                  <1> 	popf			; restore interrupt flag state
  2180                              <1> u12:	
  2181 000013AB C3                  <1> 	retn
  2182                              <1> 
  2183                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2184                              <1> 
  2185                              <1> WAITF:
  2186                              <1> waitf:
  2187                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2188                              <1> 	; 03/12/2013
  2189                              <1> 	;
  2190                              <1> ;	push	ax		; save work register (ah)	
  2191                              <1> ;waitf1:
  2192                              <1> 				; use timer 1 output bits
  2193                              <1> ;	in	al, PORT_B	; read current counter output status
  2194                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2195                              <1> ;	cmp	al, ah		; did it just change
  2196                              <1> ;	je	short waitf1	; wait for a change in output line
  2197                              <1> ;	;
  2198                              <1> ;	mov	ah, al		; save new lflag state
  2199                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2200                              <1> ;	;
  2201                              <1> ;	pop	ax		; restore (ah)
  2202                              <1> ;	retn			; return (cx)=0
  2203                              <1> 
  2204                              <1> ; 02/02/2022
  2205                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2206                              <1> ; 17/12/2014 (dsectrm2.s)
  2207                              <1> ; WAITF
  2208                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2209                              <1> ;
  2210                              <1> ;---WAITF-----------------------------------------------------------------------
  2211                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2212                              <1> ; ENTRY:
  2213                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2214                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2215                              <1> ; EXIT:
  2216                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2217                              <1> ;	(CX) = 0	
  2218                              <1> ;-------------------------------------------------------------------------------
  2219                              <1> 
  2220                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2221                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2222                              <1> 
  2223                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2224 000013AC 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2225                              <1> 	;push	ax
  2226                              <1> 	; 16/12/2014
  2227                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2228 000013AD D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2229                              <1> ;17/12/2014	
  2230                              <1> ;WAITF1:
  2231                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2232                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2233                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2234                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2235                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2236                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2237                              <1> 	;
  2238                              <1> 	; 17/12/2014
  2239                              <1> 	;
  2240                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2241                              <1> 	;
  2242                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2243                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2244                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2245                              <1> WR_STATE_0:
  2246 000013AF E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2247 000013B1 A810                <1> 	TEST	AL,010H
  2248 000013B3 74FA                <1> 	JZ	SHORT WR_STATE_0
  2249                              <1> WR_STATE_1:
  2250 000013B5 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2251 000013B7 A810                <1> 	TEST	AL,010H
  2252 000013B9 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2253 000013BB E2F2                <1>         LOOP    WR_STATE_0
  2254                              <1> 	;
  2255                              <1> 	;pop	ax
  2256 000013BD 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2257 000013BE C3                  <1> 	RETn				; (CX) = 0
  2258                              <1> 
  2259                              <1> set_cpos:
  2260                              <1> 	; 14/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20)
  2261                              <1> 	; 25/02/2022
  2262                              <1> 	; 23/02/2022
  2263                              <1> 	; 02/02/2022
  2264                              <1> 	; 27/06/2015
  2265                              <1> 	; 01/09/2014
  2266                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2267                              <1> 	;
  2268                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2269                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2270                              <1> 	;
  2271                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2272                              <1> 	;
  2273                              <1> 	; SET_CPOS
  2274                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2275                              <1> 	;	NEW X-Y VALUES PASSED
  2276                              <1> 	; INPUT
  2277                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2278                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2279                              <1> 	; OUTPUT
  2280                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2281                              <1> 	;
  2282 000013BF 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2283 000013C2 D0E0                <1>         shl     al, 1   ; word offset
  2284 000013C4 BE[56610000]        <1> 	mov	esi, cursor_posn
  2285 000013C9 01C6                <1>         add     esi, eax
  2286 000013CB 668916              <1> 	mov	[esi], dx ; save the pointer
  2287 000013CE 381D[66610000]      <1> 	cmp	[active_page], bl
  2288 000013D4 7531                <1> 	jne	short m17
  2289                              <1> 
  2290                              <1> 	; 14/06/2022	
  2291                              <1> 	;cli ; 25/02/2022
  2292                              <1> 
  2293                              <1> 	;call	m18	;h CURSOR SET
  2294                              <1> ;m17:			; SET_CPOS_RETURN
  2295                              <1> 	; 01/09/2014
  2296                              <1> 	;retn
  2297                              <1> 		; DX = row/column
  2298                              <1> m18:
  2299 000013D6 E832000000          <1> 	call	position ; determine location in regen buffer	
  2300                              <1> 	;mov	cx, [CRT_START]
  2301                              <1> 	; 23/02/2022
  2302 000013DB 0FB70D[54610000]    <1> 	movzx	ecx, word [CRT_START]
  2303 000013E2 01C1                <1> 	add	ecx, eax
  2304                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2305                              <1> 			; to the start address (offset) for this page
  2306                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2307                              <1> 	; 23/02/2022
  2308 000013E4 D1E9                <1> 	shr	ecx, 1
  2309 000013E6 B40E                <1> 	mov	ah, 14	; register number for cursor
  2310                              <1> 	
  2311                              <1> 	; 14/06/2022
  2312                              <1> 	;call	m16	; output value to the 6845
  2313                              <1> 	;sti	; 25/02/2022
  2314                              <1> 	;retn
  2315                              <1> 
  2316                              <1> 	; 14/06/2022
  2317                              <1> 	; 25/02/2022
  2318                              <1> 	; 02/02/2022
  2319                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2320                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2321                              <1> m16:
  2322                              <1> 	; 14/06/2022
  2323 000013E8 FA                  <1> 	cli	; 25/02/2022
  2324                              <1> 	;mov	dx, [addr_6845] ; address register
  2325 000013E9 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2326 000013ED 88E0                <1> 	mov	al, ah	; get value
  2327 000013EF EE                  <1> 	out	dx, al	; register set
  2328                              <1> 	;inc	dx	; data register
  2329                              <1> 	; 02/02/2022
  2330 000013F0 FEC2                <1> 	inc	dl
  2331 000013F2 EB00                <1> 	jmp	$+2	; i/o delay
  2332 000013F4 88E8                <1> 	mov	al, ch	; data
  2333 000013F6 EE                  <1> 	out	dx, al	
  2334                              <1> 	;dec	dx
  2335                              <1> 	; 02/02/2022	
  2336 000013F7 FECA                <1> 	dec	dl
  2337 000013F9 88E0                <1> 	mov	al, ah
  2338 000013FB FEC0                <1> 	inc	al	; point to other data register
  2339 000013FD EE                  <1> 	out	dx, al	; set for second register
  2340                              <1> 	;inc	dx
  2341                              <1> 	; 02/02/2022
  2342 000013FE FEC2                <1> 	inc	dl
  2343 00001400 EB00                <1> 	jmp	$+2	; i/o delay
  2344 00001402 88C8                <1> 	mov	al, cl	; second data value
  2345 00001404 EE                  <1> 	out	dx, al
  2346                              <1> 	; 14/06/2022
  2347 00001405 FB                  <1> 	sti	; 25/02/2022
  2348                              <1> ;m17:
  2349 00001406 C3                  <1> 	retn
  2350                              <1> m17:
  2351                              <1> 	; 14/06/2022
  2352                              <1> 	; ('write_tty' must not return to 'putc' with cf)
  2353 00001407 F8                  <1> 	clc
  2354 00001408 C3                  <1> 	retn
  2355                              <1> 
  2356                              <1> set_ctype:
  2357                              <1> 	; 07/02/2022
  2358                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2359                              <1> 	;
  2360                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2361                              <1> 
  2362                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2363                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2364                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2365                              <1> ;          OR NO CURSOR AT ALL
  2366                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2367                              <1> 
  2368                              <1> ;------------------------------------------------
  2369                              <1> ; SET_CTYPE
  2370                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2371                              <1> ; INPUT
  2372                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2373                              <1> ; OUTPUT	
  2374                              <1> ;	NONE
  2375                              <1> ;------------------------------------------------
  2376                              <1> 
  2377 00001409 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2378                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2379                              <1> 	;call	m16	; output cx register
  2380                              <1> 	;retn
  2381                              <1> 	; 07/02/2022
  2382 0000140B EBDB                <1> 	jmp	short m16
  2383                              <1> 
  2384                              <1> position:
  2385                              <1> 	; 23/02/2022
  2386                              <1> 	; 02/02/2022
  2387                              <1> 	; 27/06/2015
  2388                              <1> 	; 02/09/2014
  2389                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2390                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2391                              <1> 	;
  2392                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2393                              <1> 	;
  2394                              <1> 	; POSITION
  2395                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2396                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2397                              <1> 	; INPUT
  2398                              <1> 	;	AX = ROW, COLUMN POSITION
  2399                              <1> 	; OUTPUT
  2400                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2401                              <1> 
  2402                              <1> 		; DX = ROW, COLUMN POSITION
  2403                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2404 0000140D 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2405 0000140F B050                <1> 	mov	al, 80	; determine bytes to row	
  2406 00001411 F6E6                <1> 	mul	dh	; row value
  2407                              <1> 	;xor	dh, dh	; 0
  2408                              <1> 	;add	ax, dx	; add column value to the result
  2409                              <1> 	; 23/02/2022
  2410 00001413 00D0                <1> 	add	al, dl
  2411 00001415 80D400              <1> 	adc	ah, 0	
  2412                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2413                              <1> 	; 02/02/2022
  2414 00001418 D1E0                <1> 	shl	eax, 1
  2415                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2416 0000141A C3                  <1> 	retn
  2417                              <1> 
  2418                              <1> find_position:
  2419                              <1> 	; 02/02/2022
  2420                              <1> 	; 27/06/2015
  2421                              <1> 	; 07/09/2014
  2422                              <1> 	; 02/09/2014
  2423                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2424                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2425 0000141B 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2426 0000141E 89CE                <1> 	mov	esi, ecx
  2427                              <1> 	;shl	si, 1
  2428                              <1> 	; 02/02/2022
  2429 00001420 D1E6                <1> 	shl	esi, 1
  2430 00001422 668B96[56610000]    <1> 	mov	dx, [esi+cursor_posn]
  2431 00001429 7409                <1> 	jz	short p21
  2432                              <1> 	;xor	si, si
  2433                              <1> 	; 02/02/2022
  2434 0000142B 31F6                <1> 	xor	esi, esi
  2435                              <1> p20:
  2436                              <1> 	;add	si, [CRT_LEN]
  2437 0000142D 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2438 00001432 E2F9                <1> 	loop	p20
  2439                              <1> p21:
  2440 00001434 6621D2              <1> 	and	dx, dx
  2441 00001437 7407                <1> 	jz	short p22
  2442 00001439 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2443 0000143E 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2444                              <1> p22:	
  2445                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2446                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2447                              <1> 	;add	dx, 6	; point at status port
  2448 00001440 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2449                              <1> 	; cx = 0
  2450 00001444 C3                  <1> 	retn
  2451                              <1> 
  2452                              <1> scroll_up:
  2453                              <1> 	; 02/02/2022 (simplified scroll up)
  2454                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2455                              <1> 	; 16/01/2016
  2456                              <1> 	; 07/09/2014
  2457                              <1> 	; 02/09/2014
  2458                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2459                              <1> 	; 04/04/2014
  2460                              <1> 	; 04/12/2013
  2461                              <1> 	;
  2462                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2463                              <1> 	;
  2464                              <1> 	; SCROLL UP
  2465                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2466                              <1> 	;	ON THE SCREEN
  2467                              <1> 	; INPUT
  2468                              <1> 	;	(AH) = CURRENT CRT MODE
  2469                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2470                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2471                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2472                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2473                              <1> 	;	(DS) = DATA SEGMENT
  2474                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2475                              <1> 	; OUTPUT
  2476                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2477                              <1> 	;
  2478                              <1> 	;	bh = 0  (02/09/2014)
  2479                              <1> 	;
  2480                              <1> 	; ((ah = 3))
  2481                              <1> 	; cl = left upper column
  2482                              <1> 	; ch = left upper row
  2483                              <1> 	; dl = right lower column
  2484                              <1> 	; dh = right lower row
  2485                              <1> 	;
  2486                              <1> 	; al = line count 
  2487                              <1> 	; ah = attribute to be used on blanked line
  2488                              <1> 	; bl = video page number (0 to 7)
  2489                              <1> 	; 
  2490                              <1> 
  2491                              <1> 	; 02/02/2022 'scroll_up' code
  2492                              <1> 	; ------------------------------------------------------
  2493                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2494                              <1> 
  2495                              <1> 	; INPUT:
  2496                              <1> 	;		
  2497                              <1> 	; al = line count 
  2498                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2499                              <1> 	; ah = attribute to be used on blanked line
  2500                              <1> 	; bl = video page number (0 to 7)
  2501                              <1> 
  2502                              <1> 	;cli
  2503 00001445 31C9                <1> 	xor	ecx, ecx
  2504 00001447 88C1                <1> 	mov	cl, al ; line count (cl)
  2505 00001449 BE00800B00          <1> 	mov	esi, 0B8000h
  2506 0000144E 3A1D[66610000]      <1> 	cmp	bl, [active_page]
  2507 00001454 7411                <1> 	je	short n1
  2508 00001456 20DB                <1> 	and	bl, bl
  2509 00001458 7422                <1> 	jz	short n3
  2510 0000145A 88DD                <1> 	mov	ch, bl ; video page number
  2511                              <1> n0:
  2512 0000145C 6681C6A00F          <1> 	add	si, 25*80*2
  2513 00001461 FECD                <1> 	dec	ch
  2514 00001463 75F7                <1> 	jnz	short n0
  2515 00001465 EB15                <1> 	jmp	short n3
  2516                              <1> n1:
  2517 00001467 660335[54610000]    <1> 	add	si, [CRT_START]
  2518                              <1> 	;
  2519 0000146E 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2520                              <1> n2:			 ; wait_display_enable
  2521 00001472 EC                  <1> 	in	al, dx	 ; get port
  2522 00001473 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2523 00001475 74FB                <1> 	jz	short n2 ; wait_display_enable
  2524 00001477 B025                <1> 	mov	al, 25h
  2525 00001479 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2526 0000147B EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2527                              <1> n3:
  2528                              <1> 	; cl = line count
  2529                              <1> 	; ah = attribute/color
  2530 0000147C 89F7                <1> 	mov	edi, esi
  2531 0000147E 20C9                <1> 	and	cl, cl
  2532 00001480 741F                <1> 	jz	short n6
  2533 00001482 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2534 00001487 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2535 0000148B F366A5              <1> 	rep	movsw
  2536 0000148E B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2537                              <1> n4:
  2538                              <1> 	; ah = character attribute/cocor
  2539 00001490 B020                <1> 	mov	al, 20h ; fill with blanks
  2540 00001492 F366AB              <1> 	rep	stosw
  2541                              <1> 
  2542 00001495 3A1D[66610000]      <1> 	cmp	bl, [active_page]
  2543 0000149B 7503                <1> 	jne	short n5
  2544                              <1> 
  2545                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2546 0000149D B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2547                              <1> 	;mov	dx, 03D8h ; always set color card port
  2548 0000149F EE                  <1> 	out	dx, al
  2549                              <1> n5:
  2550 000014A0 C3                  <1> 	retn
  2551                              <1> n6:
  2552                              <1> 	; clear video page
  2553 000014A1 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2554 000014A5 EBE9                <1> 	jmp	short n4
  2555                              <1> 
  2556                              <1> 	; 23/02/2022
  2557                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2558                              <1> 	; ------------------------------------------------------
  2559                              <1> 
  2560                              <1> 	; Test	Line Count
  2561                              <1> 	or	al, al
  2562                              <1> 	jz	short al_set
  2563                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2564                              <1> 	sub	bh, ch
  2565                              <1> 	inc	bh	; adjust difference by 1
  2566                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2567                              <1> 	jne	short al_set ; if not the we're all set
  2568                              <1> 	xor	al, al	; otherwise set al to zero
  2569                              <1> al_set:
  2570                              <1> 	xor	bh, bh	; 0
  2571                              <1> 	;push	ax
  2572                              <1> 	push	eax ; 23/02/2022
  2573                              <1> 	;mov 	esi, [crt_base]
  2574                              <1>         mov     esi, 0B8000h  
  2575                              <1>         cmp     bl, [active_page]
  2576                              <1> 	jne	short n0
  2577                              <1> 	;
  2578                              <1>         mov     ax, [CRT_START]
  2579                              <1>         add     si, ax
  2580                              <1>         jmp     short n1
  2581                              <1> n0:
  2582                              <1>         and     bl, bl
  2583                              <1> 	jz	short n1
  2584                              <1> 	mov	al, bl
  2585                              <1> n0x:
  2586                              <1>         ;add    si, [CRT_LEN]
  2587                              <1>         ;add    esi, 80*25*2 
  2588                              <1>         add     si, 80*25*2
  2589                              <1>         dec	al
  2590                              <1> 	jnz	short n0x
  2591                              <1> n1:	
  2592                              <1>         ; Scroll position
  2593                              <1> 	;push	dx ; 23/02/2022
  2594                              <1> 	mov	dx, cx	; now, upper left position in DX
  2595                              <1> 	call	position
  2596                              <1> 	add	esi, eax
  2597                              <1> 	mov	edi, esi
  2598                              <1> 	;pop	dx	; lower right position in DX
  2599                              <1> 	sub	dx, cx
  2600                              <1> 	inc	dh	; dh = #rows 
  2601                              <1> 	inc	dl	; dl = #cols in block
  2602                              <1> 	;pop	ax	; al = line count, ah = attribute
  2603                              <1> 	pop	eax ; 23/02/2022
  2604                              <1> 	xor	ecx, ecx
  2605                              <1> 	mov	cx, ax
  2606                              <1> 	;mov	ah, [CRT_COLS]
  2607                              <1> 	mov	ah, 80
  2608                              <1> 	mul	ah	; determine offset to from address
  2609                              <1> 	add	ax, ax  ; *2 for attribute byte
  2610                              <1> 	;
  2611                              <1> 	;push	ax	; offset 
  2612                              <1> 	;push	dx
  2613                              <1> 	; 23/02/2022
  2614                              <1> 	push	eax
  2615                              <1> 	push	edx
  2616                              <1> 	;
  2617                              <1> 	; 04/04/2014
  2618                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2619                              <1> n8:                      ; wait_display_enable
  2620                              <1>         in      al, dx   ; get port
  2621                              <1> 	test	al, RVRT ; wait for vertical retrace
  2622                              <1> 	jz	short n8 ; wait_display_enable
  2623                              <1> 	mov	al, 25h
  2624                              <1> 	mov	dl, 0D8h ; address control port
  2625                              <1> 	out	dx, al	; turn off video during vertical retrace
  2626                              <1> 	;pop	dx	; #rows, #cols
  2627                              <1>        	;pop	ax	; offset
  2628                              <1> 	; 23/02/2022
  2629                              <1> 	pop	edx
  2630                              <1> 	pop	eax
  2631                              <1> 	xchg	ax, cx	; 
  2632                              <1> 	; ecx = offset, al = line count, ah = attribute
  2633                              <1> ;n9:
  2634                              <1> 	or	al, al
  2635                              <1>         jz      short n3 
  2636                              <1>         add     esi, ecx ; from address for scroll
  2637                              <1> 	mov	bh, dh  ; #rows in block
  2638                              <1> 	sub	bh, al	; #rows to be moved
  2639                              <1> n2:
  2640                              <1> 	; Move rows
  2641                              <1> 	mov	cl, dl	; get # of cols to move
  2642                              <1> 	push	esi
  2643                              <1> 	push	edi	; save start address
  2644                              <1> n10:
  2645                              <1> 	movsw		; move that line on screen
  2646                              <1> 	dec	cl
  2647                              <1>         jnz     short n10
  2648                              <1> 	pop	edi
  2649                              <1> 	pop	esi	; recover addresses
  2650                              <1>         ;mov    cl, [CRT_COLS] 
  2651                              <1> 	;add	cl, cl
  2652                              <1>         ;mov    ecx, 80*2
  2653                              <1>         mov     cx, 80*2
  2654                              <1>         add     esi, ecx  ; next line
  2655                              <1>         add     edi, ecx
  2656                              <1> 	dec	bh	 ; count of lines to move
  2657                              <1> 	jnz	short n2 ; row loop
  2658                              <1> 	; bh = 0
  2659                              <1> 	mov	dh, al	 ; #rows	
  2660                              <1> n3:
  2661                              <1> 	; attribute in ah
  2662                              <1> 	mov	al, ' '	 ; fill with blanks
  2663                              <1> n3x:
  2664                              <1> 	; Clear rows
  2665                              <1>                 ; dh =  #rows
  2666                              <1>         mov	cl, dl	; get # of cols to clear
  2667                              <1>         push    edi     ; save address
  2668                              <1> n11:
  2669                              <1>         stosw           ; store fill character
  2670                              <1> 	dec	cl
  2671                              <1>         jnz     short n11
  2672                              <1>         pop     edi     ; recover address
  2673                              <1> 	;mov	cl, [CRT_COLS]
  2674                              <1> 	;add	cl, cl
  2675                              <1>         ;mov    ecx, 80*2
  2676                              <1>         mov	cl, 80*2
  2677                              <1>         add     edi, ecx
  2678                              <1> 	dec	dh
  2679                              <1> 	jnz	short n3x ; 16/01/2016
  2680                              <1> 	;
  2681                              <1> 	cmp	bl, [active_page]
  2682                              <1> 	jne	short n6
  2683                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2684                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2685                              <1> 	mov	dx, 03D8h ; always set color card port
  2686                              <1> 	out	dx, al
  2687                              <1> n6:
  2688                              <1> 	retn
  2689                              <1> 
  2690                              <1> %endif
  2691                              <1> 
  2692                              <1> write_c_current:
  2693                              <1> 	; 02/02/2022
  2694                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2695                              <1> 	; 18/01/2014
  2696                              <1> 	; 04/12/2013
  2697                              <1> 	;
  2698                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2699                              <1> 	;
  2700                              <1> 	; WRITE_C_CURRENT
  2701                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2702                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2703                              <1> 	; INPUT	
  2704                              <1> 	;	(AH) = CURRENT CRT MODE
  2705                              <1> 	;	(BH) = DISPLAY PAGE
  2706                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2707                              <1> 	;	(AL) = CHAR TO WRITE
  2708                              <1> 	;	(DS) = DATA SEGMENT
  2709                              <1> 	;	(ES) = REGEN SEGMENT
  2710                              <1> 	; OUTPUT
  2711                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2712                              <1> 
  2713 000014A7 FA                  <1> 	cli		
  2714                              <1> 	; bl = video page
  2715                              <1> 	; al = character
  2716                              <1> 	; ah = color/attribute
  2717                              <1> 	;push	dx
  2718                              <1> 	;push	ax	; save character & attribute/color
  2719                              <1> 	; 02/02/2022
  2720 000014A8 52                  <1> 	push	edx
  2721 000014A9 50                  <1> 	push	eax
  2722 000014AA E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2723                              <1> 	; esi = regen location
  2724                              <1> 	; dx = status port
  2725                              <1> 	;
  2726                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2727                              <1> 	;
  2728                              <1> p41:			; wait for horizontal retrace is low or vertical
  2729 000014AF FB                  <1> 	sti		; enable interrupts first
  2730 000014B0 3A1D[66610000]      <1>         cmp     bl, [active_page]
  2731 000014B6 7510                <1> 	jne	short p44 
  2732 000014B8 FA                  <1> 	cli 		; block interrupts for single loop
  2733 000014B9 EC                  <1> 	in	al, dx	; get status from the adapter
  2734 000014BA A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2735 000014BC 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2736 000014BE A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2737 000014C0 75ED                <1> 	jnz	short p41 ; wait until it is
  2738                              <1> p42:			; wait for either retrace high
  2739 000014C2 EC                  <1> 	in	al, dx	; get status again
  2740 000014C3 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2741 000014C5 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2742                              <1> p43:	
  2743 000014C7 FB                  <1> 	sti
  2744                              <1> p44:
  2745                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2746                              <1> 	; 02/02/2022
  2747 000014C8 58                  <1> 	pop	eax
  2748 000014C9 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2749                              <1> 			; Retro UNIX 386 v1 feature only!
  2750 000014CF 668906              <1> 	mov	[esi], ax
  2751                              <1> 	;pop	dx
  2752                              <1> 	; 02/02/2022
  2753 000014D2 5A                  <1> 	pop	edx
  2754 000014D3 C3                  <1> 	retn
  2755                              <1> 
  2756                              <1> %if 0	; 02/02/2022
  2757                              <1> 
  2758                              <1> set_mode:
  2759                              <1> 	; 02/02/2022
  2760                              <1> 	; 16/01/2016
  2761                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2762                              <1> 	;
  2763                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2764                              <1> 
  2765                              <1> ;------------------------------------------------------
  2766                              <1> ; SET MODE					      :
  2767                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2768                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2769                              <1> ; INPUT						      :
  2770                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2771                              <1> ; OUTPUT					      :
  2772                              <1> ;	NONE					      :
  2773                              <1> ;------------------------------------------------------
  2774                              <1> 
  2775                              <1> 	push	edi ; 16/01/2016
  2776                              <1> 	push	ebx
  2777                              <1> 	push	edx
  2778                              <1> 	push	ecx ; 16/01/2016
  2779                              <1>         push    eax
  2780                              <1> 
  2781                              <1> 	;mov	dx, 03D4h 	; address or color card
  2782                              <1> 	mov	al, 3
  2783                              <1> ;M8:
  2784                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2785                              <1> 	mov	al, 29h
  2786                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2787                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2788                              <1> 	;push	dx  		; save port value
  2789                              <1> 	;add	dx, 4		; point to control register
  2790                              <1> 	mov	dx, 3D8h
  2791                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2792                              <1> 	;pop	dx
  2793                              <1> ;M9:
  2794                              <1> 	mov	ebx, video_params ; initialization table
  2795                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2796                              <1> 	;xchg 	ah, al
  2797                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2798                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2799                              <1> 	
  2800                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2801                              <1> 	; 02/02/2022
  2802                              <1> 	; dx = 3D8h
  2803                              <1> 	xor	ecx, ecx
  2804                              <1> 	mov	cl, 16
  2805                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2806                              <1> M10:			;  initialization loop
  2807                              <1> 	mov	al, ah 	; get 6845 register number
  2808                              <1> 	out	dx, al
  2809                              <1> 	;inc	dx      ; point to data port
  2810                              <1> 	; 02/02/2022
  2811                              <1> 	inc	dl ; 3D9h
  2812                              <1> 	inc	ah	; next register value
  2813                              <1> 	mov	al, [ebx] ; get table value
  2814                              <1> 	out	dx, al	; out to chip
  2815                              <1> 	inc	ebx	; next in table
  2816                              <1> 	;dec	dx	; back to pointer register
  2817                              <1> 	; 02/02/2022
  2818                              <1> 	dec	dl ; 3D8h
  2819                              <1> 	loop	M10	; do the whole table
  2820                              <1> 	
  2821                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2822                              <1> 	;xor	ax, ax  
  2823                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2824                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2825                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2826                              <1> 	; black background, light gray characeter color, space character
  2827                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2828                              <1> ;M13:			  ; clear buffer
  2829                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2830                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2831                              <1> 
  2832                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2833                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2834                              <1> 			 ; prepare to output to video enable port
  2835                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2836                              <1> 	; 02/02/2022
  2837                              <1> 	;mov	dx, 3D8h
  2838                              <1> 	; 
  2839                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2840                              <1> 	mov	al, 29h
  2841                              <1> 	out	dx, al	 ; set video enable port
  2842                              <1> 
  2843                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2844                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2845                              <1> 	;
  2846                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2847                              <1> 	;
  2848                              <1> ;-----	SET CURSOR POSITIONS
  2849                              <1> 	;push	edi
  2850                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2851                              <1> 	mov	edi, cursor_posn
  2852                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2853                              <1> 	xor	eax, eax
  2854                              <1> 	rep 	stosd	; fill with zeroes
  2855                              <1> 	;pop	edi
  2856                              <1> 
  2857                              <1> ;-----	SET UP OVERSCAN REGISTER
  2858                              <1> 	inc	dx	; set overscan port to a default
  2859                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2860                              <1> ;M14:
  2861                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2862                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2863                              <1> 
  2864                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2865                              <1> 	;
  2866                              <1> 	pop	eax
  2867                              <1> 	pop	ecx ; 16/01/2016
  2868                              <1> 	pop	edx
  2869                              <1> 	pop	ebx
  2870                              <1> 	pop	edi ; 16/01/2016
  2871                              <1> 	retn
  2872                              <1> 
  2873                              <1> %endif
  2874                              <1> 	
  2875                              <1> tty_sw:
  2876                              <1> 	; 02/02/2022
  2877                              <1> 	; 30/06/2015
  2878                              <1> 	; 27/06/2015 
  2879                              <1> 	; 07/09/2014
  2880                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2881                              <1> 	;
  2882                              <1> 	; (Modified registers : EAX)
  2883                              <1> 	;
  2884                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2885                              <1> 	;
  2886                              <1> ;act_disp_page:
  2887                              <1> 	; 30/06/2015
  2888                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2889                              <1> 	; 10/12/2013
  2890                              <1> 	; 04/12/2013
  2891                              <1> 	;
  2892                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2893                              <1> 	;
  2894                              <1> 	; ACT_DISP_PAGE
  2895                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2896                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2897                              <1> 	; INPUT
  2898                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2899                              <1> 	; OUTPUT
  2900                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2901                              <1> 
  2902                              <1> 	;cli
  2903                              <1> 
  2904 000014D4 53                  <1> 	push	ebx
  2905                              <1> 	;push	cx
  2906                              <1> 	;push	dx
  2907                              <1> 	; 02/02/2022
  2908 000014D5 51                  <1> 	push	ecx
  2909 000014D6 52                  <1> 	push	edx
  2910                              <1> 	;
  2911 000014D7 A2[66610000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2912                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2913                              <1> 	;mov	cx, 25*80*2
  2914                              <1> 	; 02/02/2022
  2915 000014DC B9A00F0000          <1> 	mov	ecx, 25*80*2
  2916                              <1> 	; 27/06/2015
  2917 000014E1 0FB6D8              <1> 	movzx	ebx, al
  2918                              <1> 	; 02/02/2022
  2919 000014E4 89D8                <1> 	mov	eax, ebx
  2920                              <1> 	;
  2921                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2922                              <1> 	;mul 	cx	; display page times regen length
  2923                              <1> 	; 02/02/2022
  2924 000014E6 F7E1                <1> 	mul	ecx	
  2925                              <1> 	; 10/12/2013
  2926 000014E8 66A3[54610000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2927                              <1> 	;mov	cx, ax	; start address to cx
  2928                              <1> 	; 02/02/2022
  2929 000014EE 89C1                <1> 	mov	ecx, eax
  2930                              <1> 	;sar	cx, 1
  2931                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2932                              <1> 	; 02/02/2022
  2933 000014F0 D1E9                <1> 	shr	ecx, 1
  2934 000014F2 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2935 000014F4 E8EFFEFFFF          <1> 	call	m16
  2936                              <1> 	;sal	bx, 1
  2937                              <1> 	; 01/09/2014
  2938 000014F9 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2939 000014FB 81C3[56610000]      <1> 	add	ebx, cursor_posn
  2940 00001501 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2941 00001504 E8CDFEFFFF          <1> 	call	m18
  2942                              <1> 	;
  2943                              <1> 	;pop	dx
  2944                              <1> 	;pop	cx
  2945                              <1> 	; 02/02/2022
  2946 00001509 5A                  <1> 	pop	edx
  2947 0000150A 59                  <1> 	pop	ecx
  2948 0000150B 5B                  <1> 	pop	ebx
  2949                              <1> 	;
  2950                              <1> 	;sti
  2951                              <1> 	;
  2952 0000150C C3                  <1> 	retn
  2953                              <1> 
  2954                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2955                              <1> 
  2956                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1836                                  
  1837                                  setup_rtc_int:
  1838                                  ; source: http://wiki.osdev.org/RTC
  1839 0000150D FA                      	cli		; disable interrupts
  1840                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1841                                  	; in order to change this ...
  1842                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1843                                  	; (rate must be above 2 and not over 15)
  1844                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1845 0000150E B08A                    	mov	al, 8Ah 
  1846 00001510 E670                    	out	70h, al ; set index to register A, disable NMI
  1847 00001512 90                      	nop
  1848 00001513 E471                    	in	al, 71h ; get initial value of register A
  1849 00001515 88C4                    	mov 	ah, al
  1850 00001517 80E4F0                  	and	ah, 0F0h
  1851 0000151A B08A                    	mov	al, 8Ah 
  1852 0000151C E670                    	out	70h, al ; reset index to register A
  1853 0000151E 88E0                    	mov	al, ah
  1854 00001520 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1855 00001522 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1856                                  	; enable RTC interrupt
  1857 00001524 B08B                    	mov	al, 8Bh ;
  1858 00001526 E670                    	out	70h, al ; select register B and disable NMI
  1859 00001528 90                      	nop
  1860 00001529 E471                    	in	al, 71h ; read the current value of register B
  1861 0000152B 88C4                    	mov	ah, al  ;
  1862 0000152D B08B                    	mov 	al, 8Bh ;
  1863 0000152F E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1864 00001531 88E0                    	mov	al, ah  ;
  1865 00001533 0C40                    	or	al, 40h ;
  1866 00001535 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1867 00001537 FB                      	sti
  1868 00001538 C3                      	retn
  1869                                  
  1870                                  ; Write memory information
  1871                                  ; Temporary Code
  1872                                  ; 06/11/2014
  1873                                  ; 14/08/2015 
  1874                                  memory_info:	
  1875 00001539 A1[3C610000]            	mov	eax, [memory_size] ; in pages
  1876 0000153E 50                      	push	eax
  1877 0000153F C1E00C                  	shl	eax, 12		   ; in bytes
  1878 00001542 BB0A000000              	mov	ebx, 10
  1879 00001547 89D9                    	mov	ecx, ebx	   ; 10
  1880 00001549 BE[A35D0000]            	mov	esi, mem_total_b_str	
  1881 0000154E E8B2000000              	call	bintdstr
  1882 00001553 58                      	pop	eax
  1883 00001554 B107                    	mov	cl, 7
  1884 00001556 BE[C75D0000]            	mov	esi, mem_total_p_str
  1885 0000155B E8A5000000              	call	bintdstr	
  1886                                  	; 14/08/2015
  1887 00001560 E8BD000000              	call	calc_free_mem
  1888                                  	; edx = calculated free pages
  1889                                  	; ecx = 0
  1890 00001565 A1[40610000]            	mov 	eax, [free_pages]
  1891 0000156A 39D0                    	cmp	eax, edx ; calculated free mem value 
  1892                                  		; and initial free mem value are same or not?
  1893 0000156C 751D                    	jne 	short pmim ; print mem info with '?' if not
  1894 0000156E 52                      	push 	edx ; free memory in pages	
  1895                                  	;mov 	eax, edx
  1896 0000156F C1E00C                  	shl	eax, 12 ; convert page count
  1897                                  			; to byte count
  1898 00001572 B10A                    	mov	cl, 10
  1899 00001574 BE[E75D0000]            	mov	esi, free_mem_b_str
  1900 00001579 E887000000              	call	bintdstr
  1901 0000157E 58                      	pop	eax
  1902 0000157F B107                    	mov	cl, 7
  1903 00001581 BE[0B5E0000]            	mov	esi, free_mem_p_str
  1904 00001586 E87A000000              	call	bintdstr
  1905                                  pmim:
  1906 0000158B BE[915D0000]            	mov	esi, msg_memory_info
  1907                                  pmim_nb:	
  1908 00001590 AC                      	lodsb
  1909 00001591 08C0                    	or	al, al
  1910 00001593 740D                    	jz	short pmim_ok
  1911 00001595 56                      	push	esi
  1912 00001596 31DB                    	xor	ebx, ebx ; 0
  1913                                  			; Video page 0 (bl=0)
  1914 00001598 B407                    	mov	ah, 07h ; Black background, 
  1915                                  			; light gray forecolor
  1916 0000159A E816FDFFFF              	call	write_tty
  1917 0000159F 5E                      	pop	esi
  1918 000015A0 EBEE                    	jmp	short pmim_nb
  1919                                  pmim_ok:
  1920 000015A2 C3                      	retn
  1921                                  
  1922                                  ; Convert binary number to hexadecimal string
  1923                                  ; 10/05/2015  
  1924                                  ; dsectpm.s (28/02/2015)
  1925                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1926                                  ; 01/12/2014
  1927                                  ; 25/11/2014
  1928                                  ;
  1929                                  bytetohex:
  1930                                  	; INPUT ->
  1931                                  	; 	AL = byte (binary number)
  1932                                  	; OUTPUT ->
  1933                                  	;	AX = hexadecimal string
  1934                                  	;
  1935 000015A3 53                      	push	ebx
  1936 000015A4 31DB                    	xor	ebx, ebx
  1937 000015A6 88C3                    	mov	bl, al
  1938 000015A8 C0EB04                  	shr	bl, 4
  1939 000015AB 8A9B[F5150000]          	mov	bl, [ebx+hexchrs] 	 	
  1940 000015B1 86D8                    	xchg	bl, al
  1941 000015B3 80E30F                  	and	bl, 0Fh
  1942 000015B6 8AA3[F5150000]          	mov	ah, [ebx+hexchrs] 
  1943 000015BC 5B                      	pop	ebx	
  1944 000015BD C3                      	retn
  1945                                  
  1946                                  wordtohex:
  1947                                  	; INPUT ->
  1948                                  	; 	AX = word (binary number)
  1949                                  	; OUTPUT ->
  1950                                  	;	EAX = hexadecimal string
  1951                                  	;
  1952 000015BE 53                      	push	ebx
  1953 000015BF 31DB                    	xor	ebx, ebx
  1954 000015C1 86E0                    	xchg	ah, al
  1955 000015C3 6650                    	push	ax
  1956 000015C5 88E3                    	mov	bl, ah
  1957 000015C7 C0EB04                  	shr	bl, 4
  1958 000015CA 8A83[F5150000]          	mov	al, [ebx+hexchrs] 	 	
  1959 000015D0 88E3                    	mov	bl, ah
  1960 000015D2 80E30F                  	and	bl, 0Fh
  1961 000015D5 8AA3[F5150000]          	mov	ah, [ebx+hexchrs]
  1962 000015DB C1E010                  	shl	eax, 16
  1963 000015DE 6658                    	pop	ax
  1964 000015E0 5B                      	pop	ebx
  1965 000015E1 EBC0                    	jmp	short bytetohex
  1966                                  	;mov	bl, al
  1967                                  	;shr	bl, 4
  1968                                  	;mov	bl, [ebx+hexchrs] 	 	
  1969                                  	;xchg	bl, al	 	
  1970                                  	;and	bl, 0Fh
  1971                                  	;mov	ah, [ebx+hexchrs] 
  1972                                  	;pop	ebx	
  1973                                  	;retn
  1974                                  
  1975                                  dwordtohex:
  1976                                  	; INPUT ->
  1977                                  	; 	EAX = dword (binary number)
  1978                                  	; OUTPUT ->
  1979                                  	;	EDX:EAX = hexadecimal string
  1980                                  	;
  1981 000015E3 50                      	push	eax
  1982 000015E4 C1E810                  	shr	eax, 16
  1983 000015E7 E8D2FFFFFF              	call	wordtohex
  1984 000015EC 89C2                    	mov	edx, eax
  1985 000015EE 58                      	pop	eax
  1986 000015EF E8CAFFFFFF              	call	wordtohex
  1987 000015F4 C3                      	retn
  1988                                  
  1989                                  ; 10/05/2015
  1990                                  hex_digits:
  1991                                  hexchrs:
  1992 000015F5 303132333435363738-     	db '0123456789ABCDEF'
  1992 000015FE 39414243444546     
  1993                                  
  1994                                  ; Convert binary number to decimal/numeric string
  1995                                  ; 06/11/2014
  1996                                  ; Temporary Code
  1997                                  ;
  1998                                  
  1999                                  bintdstr:
  2000                                  	; EAX = binary number
  2001                                  	; ESI = decimal/numeric string address
  2002                                  	; EBX = divisor (10)
  2003                                  	; ECX = string length (<=10)
  2004 00001605 01CE                    	add	esi, ecx
  2005                                  btdstr0:
  2006 00001607 4E                      	dec	esi
  2007 00001608 31D2                    	xor	edx, edx
  2008 0000160A F7F3                    	div	ebx
  2009 0000160C 80C230                  	add	dl, 30h
  2010 0000160F 8816                    	mov	[esi], dl
  2011 00001611 FEC9                    	dec	cl
  2012 00001613 740C                    	jz	btdstr2
  2013 00001615 09C0                    	or	eax, eax
  2014 00001617 75EE                    	jnz	short btdstr0
  2015                                  btdstr1:
  2016 00001619 4E                      	dec	esi
  2017 0000161A C60620                          mov     byte [esi], 20h ; blank space
  2018 0000161D FEC9                    	dec	cl
  2019 0000161F 75F8                    	jnz	short btdstr1
  2020                                  btdstr2:
  2021 00001621 C3                      	retn
  2022                                  
  2023                                  ; Calculate free memory pages on M.A.T.
  2024                                  ; 06/11/2014
  2025                                  ; Temporary Code
  2026                                  ;
  2027                                  
  2028                                  calc_free_mem:
  2029 00001622 31D2                    	xor	edx, edx
  2030                                  	;xor	ecx, ecx
  2031 00001624 668B0D[50610000]        	mov	cx, [mat_size] ; in pages
  2032 0000162B C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2033 0000162E BE00001000              	mov	esi, MEM_ALLOC_TBL
  2034                                  cfm0:
  2035 00001633 AD                      	lodsd
  2036 00001634 51                      	push	ecx
  2037 00001635 B920000000              	mov	ecx, 32
  2038                                  cfm1:
  2039 0000163A D1E8                    	shr	eax, 1
  2040 0000163C 7301                    	jnc	short cfm2
  2041 0000163E 42                      	inc	edx
  2042                                  cfm2:
  2043 0000163F E2F9                    	loop	cfm1
  2044 00001641 59                      	pop	ecx
  2045 00001642 E2EF                    	loop	cfm0
  2046 00001644 C3                      	retn
  2047                                  
  2048                                  %include 'diskio.inc'  ; 07/03/2015
  2049                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - DISKIO.INC
  2050                              <1> ; Last Modification: 18/07/2022
  2051                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2052                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2053                              <1> ; ************************************************************************
  2054                              <1> ; Ref: Retro UNIX 386 v1.1 'diskio.inc' modification: 12/07/2022
  2055                              <1> 
  2056                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2057                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2058                              <1> 
  2059                              <1> ; 15/07/2022
  2060                              <1> ;; 06/02/2015
  2061                              <1> ;diskette_io:
  2062                              <1> ;	pushfd
  2063                              <1> ;	push 	cs
  2064                              <1> ;	call 	DISKETTE_IO_1
  2065                              <1> ;	retn
  2066                              <1> 	
  2067                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2068                              <1> ;//////////////////////////////////////////////////////
  2069                              <1> 
  2070                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2071                              <1> ;		Function in AL
  2072                              <1> ;			0 = reset
  2073                              <1> ;			1 = read
  2074                              <1> ;			2 = write
  2075                              <1> ;		Disk drive number in DL
  2076                              <1> ;			0 & 1 = floppy disks	
  2077                              <1> ;			80h .. 83h = hard disks
  2078                              <1> ;		Sector address (LBA) in ECX
  2079                              <1> ;		Buffer address in EBX
  2080                              <1> ;		R/W sector count is (always) 1
  2081                              <1> ;
  2082                              <1> ;		Return:
  2083                              <1> ;			Status in AH (>0 = error code)
  2084                              <1> ;			if CF = 1 -> error code in AH
  2085                              <1> ;			if CF = 0 -> successful
  2086                              <1> ;			AL = undefined
  2087                              <1> ;
  2088                              <1> ;		Modified registers: (only) EAX
  2089                              <1> 
  2090                              <1> ; 10/07/2022
  2091                              <1> ; 08/07/2022 - (diskio code has been simplified/shortened 
  2092                              <1> ;		by removing unused IBM PC-AT disk functions)
  2093                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2094                              <1> ; 20/02/2015
  2095                              <1> ; 06/02/2015 (unix386.s)
  2096                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2097                              <1> ;
  2098                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2099                              <1> ;
  2100                              <1> ; ADISK.EQU
  2101                              <1> 
  2102                              <1> ;----- Wait control constants 
  2103                              <1> 
  2104                              <1> ;amount of time to wait while RESET is active.
  2105                              <1> 
  2106                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2107                              <1> 					;at 250 KBS xfer rate.
  2108                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2109                              <1> 
  2110                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2111                              <1> 					;status register to become valid
  2112                              <1> 					;before re-reading.
  2113                              <1> 
  2114                              <1> ;After sending a byte to NEC, status register may remain
  2115                              <1> ;incorrectly set for 24 us.
  2116                              <1> 
  2117                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2118                              <1> 					;RQM low.
  2119                              <1> 
  2120                              <1> ; COMMON.MAC
  2121                              <1> ;
  2122                              <1> ;	Timing macros
  2123                              <1> ;
  2124                              <1> 
  2125                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2126                              <1> 		jmp short $+2
  2127                              <1> %endmacro		
  2128                              <1> 
  2129                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2130                              <1> 		jmp short $+2
  2131                              <1> 		jmp short $+2
  2132                              <1> %endmacro
  2133                              <1> 
  2134                              <1> %macro		NEWIODELAY 0
  2135                              <1> 		out	0EBh,al
  2136                              <1> %endmacro 
  2137                              <1> 
  2138                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2139                              <1> ;;; WAIT_FOR_MEM
  2140                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2141                              <1> ;WAIT_FDU_INT_HI	equ	1
  2142                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2143                              <1> ;;; WAIT_FOR_PORT
  2144                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2145                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2146                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2147                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2148                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2149                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2150                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2151                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2152                              <1> ;;; WAIT_REFRESH
  2153                              <1> ;amount of time to wait for head settle, per unit in parameter
  2154                              <1> ;table = 1 ms.
  2155                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2156                              <1> 
  2157                              <1> 
  2158                              <1> ; //////////////// DISKETTE I/O ////////////////
  2159                              <1> 
  2160                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2161                              <1> 
  2162                              <1> ;----------------------------------------
  2163                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2164                              <1> ;----------------------------------------
  2165                              <1> 
  2166                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2167                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2168                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2169                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2170                              <1> 
  2171                              <1> ;----------------------------------------
  2172                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2173                              <1> ;-------------------------------------------------------------------------------
  2174                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2175                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2176                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2177                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2178                              <1> 
  2179                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2180                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2181                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2182                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2183                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2184                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2185                              <1> 
  2186                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2187                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2188                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2189                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2190                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2191                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2192                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2193                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2194                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2195                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2196                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2197                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2198                              <1> 
  2199                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2200                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2201                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2202                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2203                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2204                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2205                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2206                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2207                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2208                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2209                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2210                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2211                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2212                              <1> 
  2213                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2214                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2215                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2216                              <1> 
  2217                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2218                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2219                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2220                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2221                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2222                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2223                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2224                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2225                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2226                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2227                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2228                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2229                              <1> 
  2230                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2231                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2232                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2233                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2234                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2235                              <1> 
  2236                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2237                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2238                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2239                              <1> INTA01		EQU	021H		; 8259 PORT
  2240                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2241                              <1> INTB01		EQU	0A1H		;
  2242                              <1> 
  2243                              <1> ;-------------------------------------------------------------------------------
  2244                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2245                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2246                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2247                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2248                              <1> ;-------------------------------------------------------------------------------
  2249                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2250                              <1> 
  2251                              <1> ;-------------------------------------------------------------------------------
  2252                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2253                              <1> 
  2254                              <1> ; 10/07/2022
  2255                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2256                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2257                              <1> ; (unix386.s <-- dsectrm2.s)
  2258                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2259                              <1> 
  2260                              <1> ; 10/12/2014
  2261                              <1> ;
  2262                              <1> ;int40h:
  2263                              <1> ;	pushf
  2264                              <1> ;	push 	cs
  2265                              <1> ;	;cli
  2266                              <1> ;	call 	DISKETTE_IO_1
  2267                              <1> ;	retn
  2268                              <1> 
  2269                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2270                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2271                              <1> ;
  2272                              <1> 
  2273                              <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022-------------------------
  2274                              <1> ; DISKETTE I/O
  2275                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2276                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2277                              <1> ; INPUT
  2278                              <1> ;	(AH)= 00H RESET DISKETTE SYSTEM
  2279                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2280                              <1> ;		ON ALL DRIVES
  2281                              <1> ;------------------------------------------------------------------------------- 
  2282                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY
  2283                              <1> ;-------------------------------------------------------------------------------
  2284                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY
  2285                              <1> ;-------------------------------------------------------------------------------
  2286                              <1> ;
  2287                              <1> ;	REGISTERS FOR READ/WRITE
  2288                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2289                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2290                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2291                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2292                              <1> ;		320/360	320/360	    0-39
  2293                              <1> ;		320/360	1.2M	    0-39
  2294                              <1> ;		1.2M	1.2M	    0-79
  2295                              <1> ;		720K	720K	    0-79
  2296                              <1> ;		1.44M	1.44M	    0-79	
  2297                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED)
  2298                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2299                              <1> ;		320/360	320/360	     1-8/9
  2300                              <1> ;		320/360	1.2M	     1-8/9
  2301                              <1> ;		1.2M	1.2M	     1-15
  2302                              <1> ;		720K	720K	     1-9
  2303                              <1> ;		1.44M	1.44M	     1-18		
  2304                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2305                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2306                              <1> ;		320/360	320/360	        8/9
  2307                              <1> ;		320/360	1.2M	        8/9
  2308                              <1> ;		1.2M	1.2M		15
  2309                              <1> ;		720K	720K		9
  2310                              <1> ;		1.44M	1.44M		18
  2311                              <1> ;
  2312                              <1> ;	(EBX) - ADDRESS OF BUFFER
  2313                              <1> ;
  2314                              <1> ;-------------------------------------------------------------------------------
  2315                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2316                              <1> ;	AH = STATUS OF OPERATION
  2317                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2318                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2319                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)
  2320                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2321                              <1> ;	FOR READ/WRITE/VERIFY
  2322                              <1> ;		DS,BX,DX,CX PRESERVED
  2323                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2324                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2325                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2326                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2327                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2328                              <1> ;-------------------------------------------------------------------------------
  2329                              <1> ;
  2330                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2331                              <1> ;
  2332                              <1> ;   -----------------------------------------------------------------
  2333                              <1> ;   |       |       |       |       |       |       |       |       |
  2334                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2335                              <1> ;   |       |       |       |       |       |       |       |       |
  2336                              <1> ;   -----------------------------------------------------------------
  2337                              <1> ;	|	|	|	|	|	|	|	|
  2338                              <1> ;	|	|	|	|	|	-----------------
  2339                              <1> ;	|	|	|	|	|		|
  2340                              <1> ;	|	|	|	|    RESERVED		|
  2341                              <1> ;	|	|	|	|		  PRESENT STATE
  2342                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2343                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2344                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2345                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2346                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2347                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2348                              <1> ;	|	|	|	|	110: RESERVED
  2349                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2350                              <1> ;	|	|	|	|
  2351                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2352                              <1> ;	|	|	|
  2353                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED
  2354                              <1> ;	|	|					 (360K IN 1.2M DRIVE)
  2355                              <1> ;	|	|
  2356                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2357                              <1> ;
  2358                              <1> ;						00: 500 KBS
  2359                              <1> ;						01: 300 KBS
  2360                              <1> ;						10: 250 KBS
  2361                              <1> ;						11: RESERVED
  2362                              <1> ;
  2363                              <1> ;
  2364                              <1> 
  2365                              <1> struc MD
  2366 00000000 ??                  <1> 	.SPEC1:	  resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2367 00000001 ??                  <1> 	.SPEC2:	  resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2368 00000002 ??                  <1> 	.OFF_TIM: resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2369 00000003 ??                  <1> 	.BYT_SEC: resb	1	; 512 BYTES/SECTOR
  2370 00000004 ??                  <1> 	.SEC_TRK: resb	1	; EOT (LAST SECTOR ON TRACK)
  2371 00000005 ??                  <1> 	.GAP:	  resb	1	; GAP LENGTH
  2372 00000006 ??                  <1> 	.DTL:	  resb	1	; DTL
  2373 00000007 ??                  <1> 	.GAP3:	  resb	1	; GAP LENGTH FOR FORMAT
  2374 00000008 ??                  <1> 	.FIL_BYT: resb	1	; FILL BYTE FOR FORMAT
  2375 00000009 ??                  <1> 	.HD_TIM:  resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2376 0000000A ??                  <1> 	.STR_TIM: resb	1	; MOTOR START TIME (1/8 SECONDS)
  2377 0000000B ??                  <1> 	.MAX_TRK: resb	1	; MAX. TRACK NUMBER
  2378 0000000C ??                  <1> 	.RATE:	  resb	1	; DATA TRANSFER RATE
  2379                              <1> endstruc
  2380                              <1> 
  2381                              <1> BIT7OFF	EQU	7FH
  2382                              <1> BIT7ON	EQU	80H
  2383                              <1> 
  2384                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2385                              <1> ;		Function in AL
  2386                              <1> ;			0 = reset
  2387                              <1> ;			1 = read
  2388                              <1> ;			2 = write
  2389                              <1> ;		Disk drive number in DL
  2390                              <1> ;			0 & 1 = floppy disks	
  2391                              <1> ;			80h .. 83h = hard disks
  2392                              <1> ;		Sector address (LBA) in ECX
  2393                              <1> ;		Buffer address in EBX
  2394                              <1> ;		R/W sector count is (always) 1
  2395                              <1> ;
  2396                              <1> ;		Return:
  2397                              <1> ;			Status in AH (>0 = error code)
  2398                              <1> ;			if CF = 1 -> error code in AH
  2399                              <1> ;			if CF = 0 -> successful
  2400                              <1> ;			AL = undefined
  2401                              <1> ;
  2402                              <1> ;		Modified registers: (only) EAX
  2403                              <1> 
  2404                              <1> ; 11/07/2022
  2405                              <1> ;;int13h: ; 16/02/2015
  2406                              <1> ;; 16/02/2015 - 21/02/2015
  2407                              <1> ;int40h:
  2408                              <1> ;	pushfd
  2409                              <1> ;	push 	cs
  2410                              <1> ;	call 	DISKETTE_IO_1
  2411                              <1> ;	retn	
  2412                              <1> 
  2413                              <1> DISKETTE_IO_1:
  2414                              <1> 
  2415                              <1> 	;sti				; INTERRUPTS BACK ON
  2416                              <1> 	; 11/07/2022
  2417                              <1> 	; save registers
  2418 00001645 55                  <1> 	push	ebp			; ANY
  2419                              <1> 
  2420                              <1> 	; 11/07/2022
  2421                              <1> 	;push	edi			; ANY
  2422                              <1> 	;push	edx			; DRIVE NUMBER (DL)
  2423                              <1> 	;push	ebx			; BUFFER ADDRESS
  2424                              <1> 	;push	ecx			; SECTOR ADDRESS (LBA)
  2425                              <1> 	;push	esi			; ANY
  2426                              <1> 
  2427                              <1> 	; 11/07/2022
  2428 00001646 89DD                <1> 	mov	ebp, ebx ; buffer address
  2429 00001648 C605[BC610000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET DISKETTE STATUS
  2430 0000164F 0FB6FA              <1> 	movzx	edi, dl ; drive number (0 or 1)
  2431                              <1> 	
  2432 00001652 08C0                <1> 	or	al, al			; RESET ?
  2433 00001654 7507                <1> 	jnz	short DISKETTE_RW_1	; NO
  2434                              <1> 
  2435 00001656 E84D010000          <1> 	call	DSK_RESET
  2436                              <1> 
  2437 0000165B EB37                <1> 	jmp	short DISKETTE_RW_2	
  2438                              <1> 
  2439                              <1> DISKETTE_RW_1:
  2440                              <1> 	; 12/07/2022
  2441                              <1> 	; 11/07/2022
  2442                              <1> 	; ecx = sector address (LBA, < 2880)
  2443                              <1> 	; ebp = buffer address
  2444                              <1> 	; edi = drive number (0 or 1)
  2445                              <1> 	;  al = function (read = 1 or write = 2)
  2446                              <1> 
  2447 0000165D 88C2                <1> 	mov	dl, al ; *
  2448                              <1> convert_to_chs:
  2449                              <1> 	;;;
  2450 0000165F B004                <1> 	mov	al, 4 ; MD.SEC_TRK ; sector per track (drv.spt)
  2451 00001661 E8DB050000          <1> 	call	GET_PARM
  2452                              <1> 	; 12/07/2022
  2453 00001666 88E6                <1> 	mov	dh, ah ; spt
  2454 00001668 89C8                <1> 	mov	eax, ecx ; sector address (LBA) 
  2455 0000166A F6F6                <1> 	div	dh  ; AX/DH
  2456 0000166C 88E1                <1> 	mov	cl, ah ; sector number - 1
  2457 0000166E FEC1                <1> 	inc	cl  ; sector number (1 based)
  2458 00001670 28ED                <1> 	sub	ch, ch ; head = 0 
  2459                              <1> 	; heads = 2
  2460 00001672 D0E8                <1> 	shr	al, 1 ; al = al/2
  2461 00001674 80D500              <1> 	adc	ch, 0 ; head = 1 or head = 0
  2462 00001677 C1E110              <1> 	shl	ecx, 16
  2463 0000167A 88C1                <1> 	mov	cl, al ; track (cylinder)
  2464 0000167C 88D5                <1> 	mov	ch, dl ; function number 
  2465 0000167E 89CE                <1> 	mov	esi, ecx ; byte 0 = track, byte 1 = function
  2466                              <1> 			 ; byte 2 = sector, byte 3 = head
  2467 00001680 C1C610              <1> 	rol	esi, 16
  2468                              <1> 			 ; byte 0 = sector, byte 1 = head
  2469                              <1> 			 ; byte 2 = track, byte 3 = function		
  2470                              <1> 	;;; 
  2471 00001683 80FA02              <1> 	cmp	dl, 2 ; *
  2472 00001686 7407                <1> 	je	short DISKETTE_W
  2473                              <1> DISKETTE_R:	
  2474                              <1> 	; dl = 1 ; *
  2475 00001688 E809000000          <1> 	call	DSK_READ
  2476 0000168D EB05                <1> 	jmp	short DISKETTE_RW_2
  2477                              <1> DISKETTE_W:
  2478 0000168F E80F000000          <1> 	call	DSK_WRITE
  2479                              <1> DISKETTE_RW_2:
  2480                              <1> 	; 11/07/2022
  2481                              <1> 	; Restore registers
  2482                              <1> 	;pop	esi
  2483                              <1> 	;pop	ecx
  2484                              <1> 	;pop	ebx
  2485                              <1> 	;pop	edx
  2486                              <1> 	;pop	edi
  2487                              <1> 
  2488                              <1> 	; 11/07/2022
  2489 00001694 5D                  <1> 	pop	ebp
  2490 00001695 C3                  <1> 	retn
  2491                              <1> 
  2492                              <1> ;-------------------------------------------------------------------------------
  2493                              <1> ; DISK_READ	(AH = 01H)  ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2494                              <1> ;	DISKETTE READ.
  2495                              <1> ;
  2496                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2497                              <1> ;		SI-HI	: HEAD #
  2498                              <1> ;		SI-LOW	: # OF SECTORS
  2499                              <1> ;		ES	: BUFFER SEGMENT
  2500                              <1> ;		[BP]	: SECTOR #
  2501                              <1> ;		[BP+1]	: TRACK #
  2502                              <1> ;		[BP+2]	: BUFFER OFFSET
  2503                              <1> ;
  2504                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2505                              <1> ;-------------------------------------------------------------------------------
  2506                              <1> 
  2507                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2508                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2509                              <1> 
  2510                              <1> DSK_READ:
  2511 00001696 8025[BA610000]7F    <1> 	and	byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION
  2512 0000169D 66B846E6            <1> 	mov	ax, 0E646h		; AX = NEC COMMAND, DMA COMMAND
  2513                              <1> 	;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2514                              <1> 	;retn
  2515 000016A1 EB0B                <1> 	jmp	short RD_WR_VF
  2516                              <1> 
  2517                              <1> ;-------------------------------------------------------------------------------
  2518                              <1> ; DISK_WRITE	(AH = 02H)
  2519                              <1> ;	DISKETTE WRITE.
  2520                              <1> ;
  2521                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2522                              <1> ;		SI-HI	: HEAD #
  2523                              <1> ;		SI-LOW	: # OF SECTORS
  2524                              <1> ;		ES	: BUFFER SEGMENT
  2525                              <1> ;		[BP]	: SECTOR #
  2526                              <1> ;		[BP+1]	: TRACK #
  2527                              <1> ;		[BP+2]	: BUFFER OFFSET
  2528                              <1> ;
  2529                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2530                              <1> ;-------------------------------------------------------------------------------
  2531                              <1> 
  2532                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2533                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2534                              <1> 
  2535                              <1> DSK_WRITE:
  2536 000016A3 66B84AC5            <1> 	mov	ax, 0C54Ah		; AX = NEC COMMAND, DMA COMMAND
  2537 000016A7 800D[BA610000]80    <1>         or	byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION
  2538                              <1> 	;;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2539                              <1> 	;;retn
  2540                              <1> 	;jmp	short RD_WR_VF
  2541                              <1> 
  2542                              <1> ;-------------------------------------------------------------------------------
  2543                              <1> ; RD_WR_VF
  2544                              <1> ;	COMMON READ, WRITE
  2545                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  2546                              <1> ;
  2547                              <1> ; ON ENTRY:	AH = READ/WRITE NEC PARAMETER
  2548                              <1> ;		AL = READ/WRITE DMA PARAMETER
  2549                              <1> ;
  2550                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2551                              <1> ;-------------------------------------------------------------------------------
  2552                              <1> 
  2553                              <1> RD_WR_VF:
  2554                              <1> 	; 18/07/2022
  2555                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2556 000016AE 50                  <1> 	push	eax ; 24/12/2021	; SAVE DMA, NEC PARAMETERS
  2557 000016AF E8CB010000          <1> 	call	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2558 000016B4 E82D020000          <1> 	call	SETUP_STATE		; INITIALIZE START AND END RATE
  2559 000016B9 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2560                              <1> DO_AGAIN:
  2561 000016BA 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE PARAMETER
  2562 000016BB E867020000          <1> 	call	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  2563 000016C0 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2564                              <1> 	; 24/12/2021
  2565 000016C1 7305                <1> 	jnc	short RWV
  2566 000016C3 E9B6000000          <1> 	jmp	RWV_END			; MEDIA CHANGE ERROR OR TIME-OUT
  2567                              <1> RWV:
  2568 000016C8 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE/VERIFY PARAMETER
  2569 000016C9 8AB7[C7610000]      <1> 	mov	dh, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  2570 000016CF 80E6C0              <1> 	and	dh, RATE_MSK		; KEEP ONLY RATE
  2571 000016D2 E861050000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2572                              <1> 	; 20/02/2015
  2573 000016D7 7445                <1> 	jz	short RWV_ASSUME	; ERROR IN CMOS
  2574 000016D9 3C01                <1> 	cmp	al, 1			; 40 TRACK DRIVE?
  2575 000016DB 750D                <1> 	jne	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  2576 000016DD F687[C7610000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  2577 000016E4 740F                <1> 	jz	short RWV_2		; YES, CMOS IS CORRECT
  2578                              <1> 	;mov	al, 2			; CHANGE TO 1.2M
  2579                              <1> 	; 12/07/2022
  2580 000016E6 FEC0                <1> 	inc	al  ; al = 2
  2581 000016E8 EB0B                <1> 	jmp	short RWV_2
  2582                              <1> RWV_1:
  2583                              <1> 	; 12/07/2022
  2584                              <1> 	;jb	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  2585 000016EA F687[C7610000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK?
  2586 000016F1 7502                <1> 	jnz	short RWV_2		; NO, 80 TRACK
  2587 000016F3 B001                <1> 	mov	al, 1			; IT IS 40 TRACK, FIX CMOS VALUE
  2588                              <1> 	; 12/07/2022
  2589                              <1> 	;jmp	short RWV_3
  2590                              <1> RWV_2:
  2591                              <1> 	; 12/07/2022
  2592                              <1> 	;or	al, al			; TEST FOR NO DRIVE
  2593                              <1> 	;jz	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  2594                              <1> RWV_3:
  2595                              <1> 	; 12/07/2022
  2596                              <1> 	;mov	dl, al	; 11/07/2022
  2597 000016F5 E81F010000          <1> 	call	DR_TYPE_CHECK		; RTN EBX = MEDIA/DRIVE PARAM TBL.
  2598 000016FA 7222                <1> 	jc	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  2599                              <1> 
  2600                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  2601                              <1> 
  2602 000016FC 57                  <1> 	push	edi			; SAVE DRIVE #
  2603                              <1> 	;xor	ebx, ebx		; EBX = INDEX TO DR_TYPE TABLE
  2604 000016FD BB[DC5B0000]        <1> 	mov	ebx, DR_TYPE
  2605                              <1> 	;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2606 00001702 B106                <1> 	mov	cl, DR_CNT
  2607                              <1> RWV_DR_SEARCH:
  2608                              <1> 	;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2609 00001704 8A23                <1> 	mov	ah, [ebx]
  2610 00001706 80E47F              <1> 	and	ah, BIT7OFF		; MASK OUT MSB
  2611 00001709 38E0                <1> 	cmp	al, ah			; DRIVE TYPE MATCH?
  2612                              <1> 	; 12/07/2022
  2613                              <1> 	;cmp	dl, ah ; 11/07/2022
  2614 0000170B 7509                <1> 	jne	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  2615                              <1> RWV_DR_FND:
  2616                              <1> 	;mov	edi, [DR_TYPE+ebx+1] 	; EDI = MEDIA/DRIVE PARAMETER TABLE
  2617 0000170D 43                  <1> 	inc	ebx
  2618 0000170E 8B3B                <1> 	mov	edi, [ebx]
  2619 00001710 4B                  <1> 	dec	ebx
  2620                              <1> RWV_MD_SEARH:
  2621 00001711 3A770C              <1>         cmp	dh, [edi+MD.RATE]       ; MATCH?
  2622 00001714 741D                <1> 	je	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  2623                              <1> RWV_NXT_MD:
  2624 00001716 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2625                              <1> 	;loop	RWV_DR_SEARCH
  2626 00001719 FEC9                <1> 	dec	cl
  2627 0000171B 75E7                <1> 	jnz	short RWV_DR_SEARCH 
  2628 0000171D 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2629                              <1> 
  2630                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  2631                              <1> 
  2632                              <1> RWV_ASSUME:
  2633 0000171E BB[FA5B0000]        <1> 	mov	ebx, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  2634 00001723 F687[C7610000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK
  2635 0000172A 740A                <1> 	jz	short RWV_MD_FND1	; MUST BE 40 TRACK
  2636 0000172C BB[145C0000]        <1> 	mov	ebx, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  2637 00001731 EB03                <1> 	jmp	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  2638                              <1> 
  2639                              <1> ;-----	EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  2640                              <1> 	 			
  2641                              <1> RWV_MD_FND:
  2642 00001733 89FB                <1> 	mov	ebx, edi		; EBX = MEDIA/DRIVE PARAMETER TABLE
  2643 00001735 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2644                              <1> 	
  2645                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  2646                              <1> 
  2647                              <1> RWV_MD_FND1:
  2648 00001736 E824010000          <1> 	call	SEND_SPEC_MD
  2649 0000173B E853020000          <1> 	call	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  2650 00001740 7405                <1> 	jz	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  2651 00001742 E82E020000          <1> 	call	SEND_RATE		; SEND DATA RATE TO NEC
  2652                              <1> RWV_DBL:
  2653 00001747 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2654 00001748 E849040000          <1> 	call	SETUP_DBL		; CHECK FOR DOUBLE STEP
  2655 0000174D 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2656 0000174E 7221                <1> 	jc	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  2657                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2658                              <1> 	;push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2659                              <1> 	; 08/07/2022
  2660 00001750 8B0424              <1> 	mov	eax, [esp]
  2661                              <1> 	; 18/07/2022
  2662                              <1> 	;push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2663 00001753 E84E020000          <1> 	call	DMA_SETUP		; SET UP THE DMA
  2664                              <1> 	;pop	ebx
  2665 00001758 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2666 00001759 722D                <1> 	jc	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  2667 0000175B 50                  <1> 	push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2668 0000175C 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2669 0000175D E88E020000          <1> 	call	NEC_INIT		; INITIALIZE NEC
  2670 00001762 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2671 00001763 720C                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2672 00001765 E8B7020000          <1> 	call	RWV_COM			; OP CODE COMMON TO READ/WRITE
  2673 0000176A 7205                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2674 0000176C E8FE020000          <1> 	call	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  2675                              <1> CHK_RET:
  2676 00001771 E89D030000          <1> 	call	RETRY			; CHECK FOR, SETUP RETRY
  2677 00001776 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2678 00001777 7305                <1> 	jnc	short RWV_END		; CY = 0 NO RETRY
  2679 00001779 E93CFFFFFF          <1>         jmp	DO_AGAIN                ; CY = 1 MEANS RETRY
  2680                              <1> RWV_END:
  2681 0000177E E848030000          <1> 	call	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  2682 00001783 E8D9030000          <1> 	call	NUM_TRANS		; AL = NUMBER TRANSFERRED
  2683                              <1> RWV_BAC:
  2684                              <1> 	; 08/07/2022			; BAD DMA ERROR ENTRY
  2685                              <1> 	;push	eax ; 24/12/2021	; SAVE NUMBER TRANSFERRED
  2686                              <1> 	;CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2687                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NUMBER TRANSFERRED
  2688                              <1> 	;;call	SETUP_END		; VARIOUS CLEANUPS
  2689                              <1> 	;;retn
  2690                              <1> 	;jmp	SETUP_END
  2691                              <1> 
  2692                              <1> ;-------------------------------------------------------------------------------
  2693                              <1> ; SETUP_END
  2694                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  2695                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  2696                              <1> ;
  2697                              <1> ; ON EXIT:
  2698                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2699                              <1> ;-------------------------------------------------------------------------------
  2700                              <1> SETUP_END:
  2701                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 
  2702                              <1> 	;mov	dl, 2			; GET THE MOTOR WAIT PARAMETER
  2703                              <1> 	;push	ax			; SAVE NUMBER TRANSFERRED
  2704 00001788 50                  <1> 	push	eax ; 24/12/2021
  2705 00001789 B002                <1> 	mov	al, 2 ; 08/07/2022
  2706 0000178B E8B1040000          <1> 	call	GET_PARM
  2707 00001790 8825[BB610000]      <1> 	mov	[MOTOR_COUNT], ah	; STORE UPON RETURN
  2708                              <1> 	;pop	ax			; RESTORE NUMBER TRANSFERRED
  2709 00001796 58                  <1> 	pop	eax ; 24/12/2021
  2710 00001797 8A25[BC610000]      <1> 	mov	ah, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  2711 0000179D 08E4                <1> 	or	ah, ah			; CHECK FOR ERROR
  2712 0000179F 7406                <1> 	jz	short NUN_ERR		; NO ERROR
  2713 000017A1 30C0                <1> 	xor 	al, al			; CLEAR NUMBER RETURNED
  2714                              <1> ;NUN_ERR: 
  2715 000017A3 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  2716 000017A6 F5                  <1> 	cmc				; SUCCESS OR FAILURE
  2717                              <1> NUN_ERR:
  2718 000017A7 C3                  <1> 	retn
  2719                              <1> 
  2720                              <1> ;-------------------------------------------------------------------------------
  2721                              <1> ; DISK_RESET	(AH = 00H)	
  2722                              <1> ;		RESET THE DISKETTE SYSTEM.
  2723                              <1> ;
  2724                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2725                              <1> ;-------------------------------------------------------------------------------
  2726                              <1> DSK_RESET:
  2727                              <1> 	; 17/07/2022
  2728                              <1> 	; 12/07/2022
  2729                              <1> 	; 11/07/2022
  2730                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2731 000017A8 66BAF203            <1> 	mov	dx, 03F2h		; ADAPTER CONTROL PORT
  2732 000017AC FA                  <1> 	cli				; NO INTERRUPTS
  2733 000017AD A0[BA610000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2734 000017B2 243F                <1> 	and	al, 00111111b		; KEEP SELECTED AND MOTOR ON BITS
  2735 000017B4 C0C004              <1> 	rol	al, 4			; MOTOR VALUE TO HIGH NIBBLE
  2736                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2737 000017B7 0C08                <1> 	or	al, 00001000b		; TURN ON INTERRUPT ENABLE
  2738 000017B9 EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2739 000017BA C605[B9610000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2740                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2741                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2742                              <1> 					;      PULSE WIDTH)
  2743                              <1> 	; 19/12/2014
  2744                              <1> 	NEWIODELAY
  2135 000017C1 E6EB                <2>  out 0EBh,al
  2745                              <1> 
  2746                              <1> 	; 17/12/2014 
  2747                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2748 000017C3 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2749                              <1> wdw1:
  2750                              <1> 	NEWIODELAY   ; 27/02/2015
  2135 000017C8 E6EB                <2>  out 0EBh,al
  2751 000017CA E2FC                <1> 	loop	wdw1
  2752                              <1> 	;
  2753 000017CC 0C04                <1> 	or	al, 00000100b		; TURN OFF RESET BIT
  2754 000017CE EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2755                              <1> 	; 16/12/2014
  2756                              <1> 	IODELAY
  2130 000017CF EB00                <2>  jmp short $+2
  2131 000017D1 EB00                <2>  jmp short $+2
  2757                              <1> 	;
  2758                              <1> 	;sti				; ENABLE THE INTERRUPTS
  2759 000017D3 E864060000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  2760 000017D8 7236                <1> 	jc	short DR_ERR		; IF ERROR, RETURN IT
  2761                              <1> 	;mov	cx, 11000000b		; CL = EXPECTED @NEC_STATUS
  2762                              <1> 	; 12/07/2022
  2763                              <1> 	;xor	ecx, ecx
  2764                              <1> 	; 17/07/2022
  2765                              <1> 	;xor	ch, ch
  2766 000017DA B1C0                <1> 	mov	cl, 11000000b
  2767                              <1> NXT_DRV:
  2768                              <1> 	; 24/12/2021
  2769 000017DC 51                  <1> 	push	ecx			; SAVE FOR CALL
  2770 000017DD B8[0F180000]        <1> 	mov	eax, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2771 000017E2 50                  <1> 	push	eax			;
  2772 000017E3 B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  2773 000017E5 E848050000          <1> 	call	NEC_OUTPUT
  2774 000017EA 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  2775 000017EB E87B060000          <1> 	call	RESULTS			; READ IN THE RESULTS
  2776                              <1> 	; 24/12/2021
  2777 000017F0 59                  <1> 	pop	ecx			; RESTORE AFTER CALL
  2778 000017F1 721D                <1> 	jc	short DR_ERR		; ERROR RETURN
  2779 000017F3 3A0D[BD610000]      <1> 	cmp	cl, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2780 000017F9 7515                <1> 	jnz	short DR_ERR		; EVERYTHING OK
  2781 000017FB FEC1                <1> 	inc	cl			; NEXT EXPECTED @NEC_STATUS
  2782 000017FD 80F9C3              <1> 	cmp	cl, 11000011b		; ALL POSSIBLE DRIVES CLEARED
  2783 00001800 76DA                <1> 	jbe	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2784                              <1> 	;
  2785 00001802 E82F000000          <1> 	call	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2786                              <1> RESBAC:
  2787 00001807 E87CFFFFFF          <1> 	call	SETUP_END		; VARIOUS CLEANUPS
  2788                              <1> 	
  2789                              <1> 	; 11/07/2022
  2790                              <1> 	; CF = 1 -> error (error code in AH)
  2791                              <1> 	; CF = 0 -> OK
  2792                              <1> 	
  2793                              <1> 	;; 24/12/2021
  2794                              <1> 	;mov	ebx, esi		; GET SAVED AL TO BL
  2795                              <1> 	;; 11/07/2022
  2796                              <1> 	;; byte 0 = sector, byte 1 = head, byte 2 = track, byte 3 = function 
  2797                              <1> 	;rol	ebx, 8
  2798                              <1> 	; bl = function (reset = 0)
  2799                              <1> 	;
  2800                              <1> 	;mov	al, bl			; PUT BACK FOR RETURN
  2801                              <1> 	
  2802                              <1> 	; 11/07/2022  
  2803 0000180C B000                <1> 	mov	al, 0	; (reset function = 0)
  2804                              <1> 
  2805 0000180E C3                  <1> 	retn
  2806                              <1> 
  2807                              <1> DR_POP_ERR:
  2808                              <1> 	; 24/12/2021
  2809 0000180F 59                  <1> 	pop	ecx			; CLEAR STACK
  2810                              <1> DR_ERR:
  2811 00001810 800D[BC610000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE
  2812 00001817 EBEE                <1> 	jmp	short RESBAC		; RETURN FROM RESET
  2813                              <1> 
  2814                              <1> ;-------------------------------------------------------------------------------
  2815                              <1> ; FNC_ERR
  2816                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2817                              <1> ;	SET BAD COMMAND IN STATUS.
  2818                              <1> ;
  2819                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2820                              <1> ;-------------------------------------------------------------------------------
  2821                              <1> 
  2822                              <1> 	; 11/07/2022 - not needed (because diskio is used by kernel only)
  2823                              <1> 	
  2824                              <1> ;FNC_ERR:				; INVALID FUNCTION REQUEST
  2825                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2826                              <1> ;	; 24/12/2021
  2827                              <1> ;	mov	eax, esi		; RESTORE AL
  2828                              <1> ;	mov	ah, BAD_CMD		; SET BAD COMMAND ERROR
  2829                              <1> ;	mov	[DSKETTE_STATUS], ah	; STORE IN DATA AREA
  2830                              <1> ;	stc				; SET CARRY INDICATING ERROR
  2831                              <1> ;	retn
  2832                              <1> 
  2833                              <1> 
  2834                              <1> ;----------------------------------------------------------------
  2835                              <1> ; DR_TYPE_CHECK							:
  2836                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  2837                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  2838                              <1> ; ON ENTRY:							:
  2839                              <1> ;	AL = DRIVE TYPE						:
  2840                              <1> ; ON EXIT:							:
  2841                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  2842                              <1> ;	     EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE	:
  2843                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  2844                              <1> ; REGISTERS ALTERED: EBX, AH ; 11/07/2022 			:
  2845                              <1> ;----------------------------------------------------------------
  2846                              <1> DR_TYPE_CHECK:
  2847                              <1> 	; 12/07/2022
  2848                              <1> 	; 11/07/2022
  2849                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2850                              <1> 	; 24/12/2021
  2851                              <1> 	;push	eax ; 11/07/2022
  2852                              <1> 	;push	ecx ; 08/07/2022
  2853                              <1> 	;xor	ebx,ebx			; EBX = INDEX TO DR_TYPE TABLE
  2854 00001819 BB[DC5B0000]        <1> 	mov	ebx, DR_TYPE
  2855                              <1> 	;;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2856                              <1> 	;mov	cl, DR_CNT
  2857 0000181E B406                <1> 	mov	ah, DR_CNT ; 11/07/2022
  2858                              <1> TYPE_CHK:	
  2859                              <1> 	;;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2860                              <1> 	;mov	ah, [ebx]
  2861                              <1> 	;cmp	al, ah			; DRIVE TYPE MATCH?
  2862 00001820 3A03                <1> 	cmp	al, [ebx] ; 11/07/2022
  2863 00001822 740E                <1> 	je	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  2864                              <1> 	; 16/02/2015 (32 bit address modification)
  2865 00001824 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2866                              <1> 	;loop	TYPE_CHK
  2867                              <1> 	;dec	cl
  2868 00001827 FECC                <1> 	dec	ah ; 11/07/2022
  2869 00001829 75F5                <1> 	jnz	short TYPE_CHK
  2870                              <1> 	;
  2871 0000182B BB[3B5C0000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  2872                              <1> 					; Default for GET_PARM (11/12/2014)
  2873                              <1> 	;
  2874 00001830 F9                  <1> 	stc				; DRIVE TYPE NOT FOUND IN TABLE
  2875                              <1> 	;jmp	short TYPE_RTN
  2876                              <1> 	; 12/07/2022
  2877 00001831 C3                  <1> 	retn
  2878                              <1> DR_TYPE_VALID:
  2879                              <1> 	;mov	ebx, [DR_TYPE+ebx+1] 	; EBX = MEDIA TABLE
  2880 00001832 43                  <1> 	inc	ebx
  2881 00001833 8B1B                <1> 	mov	ebx, [ebx]
  2882                              <1> TYPE_RTN:
  2883                              <1> 	;pop	ecx ; 08/07/2022
  2884                              <1> 	; 24/12/2021
  2885                              <1> 	;pop	eax ; 11/07/2022
  2886 00001835 C3                  <1> 	retn		
  2887                              <1> 
  2888                              <1> ;----------------------------------------------------------------
  2889                              <1> ; SEND_SPEC							:
  2890                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2891                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  2892                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  2893                              <1> ; ON EXIT:	NONE						:	
  2894                              <1> ; REGISTERS ALTERED: ECX, EDX					:
  2895                              <1> ;----------------------------------------------------------------		
  2896                              <1> SEND_SPEC:
  2897                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2898 00001836 50                  <1> 	push	eax			; SAVE EAX
  2899 00001837 B8[5D180000]        <1> 	mov	eax, SPECBAC		; LOAD ERROR ADDRESS
  2900 0000183C 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2901 0000183D B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2902 0000183F E8EE040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2903                              <1> 	;sub	dl, dl			; FIRST SPECIFY BYTE
  2904 00001844 28C0                <1> 	sub	al, al ; 08/07/2022
  2905 00001846 E8F6030000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2906 0000184B E8E2040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2907                              <1> 	;mov	dl, 1			; SECOND SPECIFY BYTE
  2908 00001850 B001                <1> 	mov	al, 1 ; 08/07/2022
  2909 00001852 E8EA030000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2910 00001857 E8D6040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2911 0000185C 58                  <1> 	pop	eax			; POP ERROR RETURN
  2912                              <1> SPECBAC:
  2913 0000185D 58                  <1> 	pop	eax			; RESTORE ORIGINAL EAX VALUE
  2914 0000185E C3                  <1> 	retn
  2915                              <1> 
  2916                              <1> ;----------------------------------------------------------------
  2917                              <1> ; SEND_SPEC_MD							:
  2918                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2919                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  2920                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  2921                              <1> ; ON EXIT:	NONE						:	
  2922                              <1> ; REGISTERS ALTERED: AX						:
  2923                              <1> ;----------------------------------------------------------------		
  2924                              <1> SEND_SPEC_MD:
  2925 0000185F 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  2926 00001860 B8[7D180000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  2927 00001865 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2928 00001866 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  2929 00001868 E8C5040000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  2930 0000186D 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  2931 0000186F E8BE040000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  2932 00001874 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  2933 00001877 E8B6040000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  2934 0000187C 58                  <1> 	POP	eAX			; POP ERROR RETURN
  2935                              <1> SPEC_ESBAC:
  2936 0000187D 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  2937 0000187E C3                  <1> 	RETn
  2938                              <1> 
  2939                              <1> ;-------------------------------------------------------------------------------
  2940                              <1> ; XLAT_NEW  
  2941                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  2942                              <1> ;	MODE TO NEW ARCHITECTURE.
  2943                              <1> ;
  2944                              <1> ; ON ENTRY:	EDI = DRIVE #
  2945                              <1> ;-------------------------------------------------------------------------------
  2946                              <1> XLAT_NEW:
  2947                              <1> 	; 11/07/2022
  2948                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2949                              <1> 	;cmp	edi, 1				; VALID DRIVE
  2950                              <1> 	;ja	short XN_OUT			; IF INVALID BACK
  2951                              <1> 	;
  2952 0000187F 80BF[C7610000]00    <1> 	cmp	byte [DSK_STATE+edi], 0		; NO DRIVE ?
  2953 00001886 7401                <1> 	jz	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  2954                              <1> 	;
  2955                              <1> 	;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2956                              <1> 	;mov	ecx, edi			; ECX = DRIVE NUMBER
  2957                              <1> 	;or	cl, cl
  2958                              <1> 	;jz	short XN_0  ; 08/07/2022
  2959                              <1> 	;shl	cl, 2				; CL = SHIFT COUNT, A=0, B=4
  2960                              <1> 	;;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2961                              <1> 	;ror	al, cl				; TO LOW NIBBLE
  2962                              <1> ;XN_0:	
  2963                              <1> 	;and	al, DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  2964                              <1>         ;and	byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  2965                              <1> 	;or	[DSK_STATE+edi], al		; UPDATE DRIVE STATE
  2966                              <1> XN_OUT:
  2967 00001888 C3                  <1> 	retn
  2968                              <1> DO_DET:
  2969                              <1> 	;;call	DRIVE_DET			; TRY TO DETERMINE
  2970                              <1> 	;;retn
  2971                              <1> 	;jmp	DRIVE_DET
  2972                              <1> 
  2973                              <1> ;-------------------------------------------------------------------------------
  2974                              <1> ; DRIVE_DET
  2975                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  2976                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  2977                              <1> ; ON ENTRY:	EDI = DRIVE #
  2978                              <1> ;-------------------------------------------------------------------------------
  2979                              <1> DRIVE_DET:
  2980                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2981 00001889 E8EE030000          <1> 	call	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  2982 0000188E E857050000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  2983 00001893 724E                <1> 	jc	short DD_BAC		; ASSUME NO DRIVE PRESENT
  2984 00001895 B530                <1> 	mov	ch, TRK_SLAP		; SEEK TO TRACK 48
  2985 00001897 E8CF040000          <1> 	call	SEEK
  2986 0000189C 7245                <1> 	jc	short DD_BAC		; ERROR NO DRIVE
  2987 0000189E B50B                <1> 	mov	ch, QUIET_SEEK+1	; SEEK TO TRACK 10
  2988                              <1> SK_GIN:
  2989 000018A0 FECD                <1> 	dec	ch			; DECREMENT TO NEXT TRACK
  2990                              <1> 	;push	cx		
  2991                              <1> 	; 24/12/2021
  2992 000018A2 51                  <1> 	push	ecx			; SAVE TRACK
  2993 000018A3 E8C3040000          <1> 	call	SEEK
  2994 000018A8 723A                <1> 	jc	short POP_BAC		; POP AND RETURN
  2995 000018AA B8[E4180000]        <1> 	mov	eax, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  2996 000018AF 50                  <1> 	push	eax
  2997 000018B0 B404                <1> 	mov	ah, SENSE_DRV_ST	; SENSE DRIVE STATUS COMMAND BYTE
  2998 000018B2 E87B040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  2999                              <1> 	; 08/07/2022
  3000 000018B7 89F8                <1> 	mov	eax, edi		; AL = DRIVE
  3001 000018B9 88C4                <1> 	mov	ah, al			; AH = DRIVE
  3002 000018BB E872040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  3003 000018C0 E8A6050000          <1> 	call	RESULTS			; GO GET STATUS
  3004 000018C5 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3005                              <1> 	;pop	cx			; RESTORE TRACK
  3006                              <1> 	; 24/12/2021
  3007 000018C6 59                  <1> 	pop	ecx
  3008 000018C7 F605[BD610000]10    <1> 	test	byte [NEC_STATUS], HOME	; TRACK 0 ?
  3009 000018CE 74D0                <1> 	jz	short SK_GIN		; GO TILL TRACK 0
  3010 000018D0 08ED                <1> 	or	ch, ch			; IS HOME AT TRACK 0
  3011 000018D2 7408                <1> 	jz	short IS_80		; MUST BE 80 TRACK DRIVE
  3012                              <1> 
  3013                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  3014                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  3015                              <1> 
  3016 000018D4 808F[C7610000]94    <1> 	or	byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250
  3017 000018DB C3                  <1> 	retn				; ALL INFORMATION SET
  3018                              <1> IS_80:
  3019 000018DC 808F[C7610000]01    <1> 	or	byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  3020                              <1> DD_BAC:
  3021 000018E3 C3                  <1> 	retn
  3022                              <1> POP_BAC:
  3023                              <1> 	;pop	cx			; THROW AWAY
  3024                              <1> 	; 24/12/2021
  3025 000018E4 59                  <1> 	pop	ecx
  3026 000018E5 C3                  <1> 	retn
  3027                              <1> 
  3028                              <1> ;-------------------------------------------------------------------------------
  3029                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3030                              <1> ;-------------------------------------------------------------------------------
  3031                              <1> SETUP_STATE:
  3032                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3033 000018E6 F687[C7610000]10    <1> 	test	byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ?
  3034 000018ED 7537                <1> 	jnz	short J1C		; NO STATES IF DETERMINED
  3035 000018EF 66B84000            <1>        	mov	ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE
  3036 000018F3 F687[C7610000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE ?
  3037 000018FA 740D                <1> 	jz	short AX_SET		; DO NOT KNOW DRIVE
  3038 000018FC F687[C7610000]02    <1> 	test	byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE?
  3039 00001903 7504                <1> 	jnz	short AX_SET		; JUMP IF YES
  3040 00001905 66B88080            <1>         mov	ax, RATE_250*257	; START A END RATE 250 FOR 360 DRIVE
  3041                              <1> AX_SET:	
  3042 00001909 80A7[C7610000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3043 00001910 08A7[C7610000]      <1> 	or	[DSK_STATE+edi], ah	; RATE FIRST TO TRY
  3044 00001916 8025[C4610000]F3    <1> 	and	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3045 0000191D C0C804              <1> 	ror	al, 4			; TO OPERATION LAST RATE LOCATION
  3046 00001920 0805[C4610000]      <1> 	or	[LASTRATE], al		; LAST RATE
  3047                              <1> J1C:	
  3048 00001926 C3                  <1> 	retn
  3049                              <1> 
  3050                              <1> ;-------------------------------------------------------------------------------
  3051                              <1> ; MED_CHANGE	
  3052                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3053                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3054                              <1> ;
  3055                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3056                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3057                              <1> ;-------------------------------------------------------------------------------
  3058                              <1> MED_CHANGE:
  3059                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3060 00001927 E897050000          <1> 	call	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3061 0000192C 7446                <1> 	jz	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3062 0000192E 80A7[C7610000]EF    <1> 	and	byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3063                              <1> 
  3064                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3065                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3066                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3067                              <1> 
  3068 00001935 89F9                <1> 	mov	ecx, edi		; CL = DRIVE #
  3069 00001937 B001                <1> 	mov	al, 1			; MOTOR ON BIT MASK
  3070 00001939 D2E0                <1> 	shl	al, cl			; TO APPROPRIATE POSITION
  3071 0000193B F6D0                <1> 	not	al			; KEEP ALL BUT MOTOR ON
  3072 0000193D FA                  <1> 	cli				; NO INTERRUPTS
  3073 0000193E 2005[BA610000]      <1> 	and	[MOTOR_STATUS], al	; TURN MOTOR OFF INDICATOR
  3074 00001944 FB                  <1> 	sti				; INTERRUPTS ENABLED
  3075 00001945 E832030000          <1> 	call	MOTOR_ON		; TURN MOTOR ON
  3076                              <1> 
  3077                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3078                              <1> 
  3079 0000194A E859FEFFFF          <1> 	call	DSK_RESET		; RESET NEC
  3080 0000194F B501                <1> 	mov	ch, 1			; MOVE TO CYLINDER 1
  3081 00001951 E815040000          <1> 	call	SEEK			; ISSUE SEEK
  3082 00001956 30ED                <1> 	xor	ch, ch			; MOVE TO CYLINDER 0
  3083 00001958 E80E040000          <1> 	call	SEEK			; ISSUE SEEK
  3084 0000195D C605[BC610000]06    <1> 	mov	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3085                              <1> OK1:
  3086 00001964 E85A050000          <1> 	call	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3087 00001969 7407                <1> 	jz	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3088                              <1> OK4:
  3089 0000196B C605[BC610000]80    <1> 	mov	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3090                              <1> OK2:		
  3091 00001972 F9                  <1> 	stc				; MEDIA CHANGED, SET CY
  3092 00001973 C3                  <1> 	retn
  3093                              <1> MC_OUT:
  3094                              <1> 	;clc	; 08/07/2022		; NO MEDIA CHANGED, CLEAR CY
  3095 00001974 C3                  <1> 	retn
  3096                              <1> 
  3097                              <1> ;-------------------------------------------------------------------------------
  3098                              <1> ; SEND_RATE
  3099                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3100                              <1> ; ON ENTRY:	EDI = DRIVE #
  3101                              <1> ; ON EXIT:	NONE
  3102                              <1> ; REGISTERS ALTERED: EDX, EAX ; 11/07/2022
  3103                              <1> ;-------------------------------------------------------------------------------
  3104                              <1> SEND_RATE:
  3105                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5
  3106                              <1> 	;push	ax			; SAVE REG.
  3107                              <1> 	; 24/12/2021
  3108                              <1> 	;push	eax ; 11/07/2022
  3109 00001975 8025[C4610000]3F    <1> 	and	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3110 0000197C 8A87[C7610000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3111 00001982 24C0                <1> 	and	al, SEND_MSK		; KEEP ONLY RATE BITS
  3112 00001984 0805[C4610000]      <1> 	or	[LASTRATE], al		; SAVE NEW RATE FOR NEXT CHECK
  3113 0000198A C0C002              <1> 	rol	al, 2			; MOVE TO BIT OUTPUT POSITIONS
  3114 0000198D 66BAF703            <1> 	mov	dx, 03F7h		; OUTPUT NEW DATA RATE
  3115 00001991 EE                  <1> 	out	dx, al
  3116                              <1> 	;pop	ax			; RESTORE REG.
  3117                              <1> 	; 24/12/2021
  3118                              <1> 	;pop	eax ; 11/07/2022
  3119 00001992 C3                  <1> 	retn
  3120                              <1> 
  3121                              <1> ;-------------------------------------------------------------------------------
  3122                              <1> ; CHK_LASTRATE
  3123                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3124                              <1> ; ON ENTRY:
  3125                              <1> ;	EDI = DRIVE #
  3126                              <1> ; ON EXIT:
  3127                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3128                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3129                              <1> ; REGISTERS ALTERED: EAX ; 11/07/2022
  3130                              <1> ;-------------------------------------------------------------------------------
  3131                              <1> CHK_LASTRATE:
  3132                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3133                              <1> 	;push	ax			; SAVE REG.
  3134                              <1> 	; 24/12/2021
  3135                              <1> 	;push	eax ; 11/07/2022
  3136 00001993 8A25[C4610000]      <1> 	mov	ah, [LASTRATE] ; 08/07/2022 (BugFix) 
  3137                              <1> 					; GET LAST DATA RATE SELECTED
  3138 00001999 8A87[C7610000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3139 0000199F 6625C0C0            <1>        	and	ax, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3140 000019A3 38E0                <1> 	cmp	al, ah			; COMPARE TO PREVIOUSLY TRIED
  3141                              <1> 					; ZF = 1 RATE IS THE SAME
  3142                              <1> 	;pop	ax			; RESTORE REG.
  3143                              <1> 	; 24/12/2021
  3144                              <1> 	;pop	eax ; 11/07/2022
  3145 000019A5 C3                  <1> 	retn
  3146                              <1> 
  3147                              <1> ;-------------------------------------------------------------------------------
  3148                              <1> ; DMA_SETUP
  3149                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3150                              <1> ;
  3151                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3152                              <1> ;
  3153                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3154                              <1> ;-------------------------------------------------------------------------------
  3155                              <1> 
  3156                              <1> ; SI = Head #, # of Sectors or DASD Type
  3157                              <1> 
  3158                              <1> ; 22/08/2015
  3159                              <1> ; 08/02/2015 - Protected Mode Modification
  3160                              <1> ; 06/02/2015 - 07/02/2015
  3161                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3162                              <1> ; (DMA Addres = Physical Address)
  3163                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3164                              <1> ;
  3165                              <1> ; 04/02/2016 (clc)
  3166                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3167                              <1> ; 16/12/2014 (IODELAY)
  3168                              <1> 
  3169                              <1> DMA_SETUP:
  3170                              <1> 	; 18/07/2022
  3171                              <1> 	; 11/07/2022
  3172                              <1> 	;	ebp = buffer address
  3173                              <1> 	
  3174                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3175                              <1> 	;; 20/02/2015
  3176                              <1> 	;mov	edx, [ebp+4] ; 11/07/2022 ; Buffer address
  3177                              <1> 	; 08/07/2022 - not needed for Retro UNIX 386 v1.1
  3178                              <1> 	;test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3179                              <1> 	;jnz	short dma_bnd_err_stc
  3180                              <1> 
  3181                              <1> 	; al = dma command
  3182                              <1> 	
  3183                              <1> ;	; 18/07/2022
  3184                              <1> ;	;	(512 bytes/sector only!) 
  3185                              <1> ;	; 24/12/2021
  3186                              <1> ;	push	eax			; DMA command
  3187                              <1> ;	;push	edx ; 11/07/2022	; *
  3188                              <1> ;	;mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3189                              <1> ;	mov	al, 3 ; 08/07/2022
  3190                              <1> ;	call	GET_PARM		; 
  3191                              <1> ;	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3192                              <1> ;	;mov	ax, si			; Sector count
  3193                              <1> ;	;mov	ah, al			; AH = # OF SECTORS
  3194                              <1> ;	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3195                              <1> ;	;shr	ax, 1			; AX = # SECTORS * 128
  3196                              <1> ;	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3197                              <1> ;	; 08/07/2022
  3198                              <1> ;	; 24/12/2021
  3199                              <1> ;	;mov	edx, esi
  3200                              <1> ;	sub	eax, eax
  3201                              <1> ;	;mov	ah, dl
  3202                              <1> ;	;shr	eax, 1
  3203                              <1> ;	mov	al, 128
  3204                              <1> ;	shl	eax, cl
  3205                              <1> ;	;
  3206                              <1> ;	dec	eax			; -1 FOR DMA VALUE
  3207                              <1> ;	mov	ecx, eax
  3208                              <1> ;	;pop	edx ; 11/07/2022	; *
  3209                              <1> ;	; 24/12/2021
  3210                              <1> ;	pop	eax
  3211                              <1> 
  3212                              <1> 	; 08/07/2022
  3213                              <1> 	;cmp	al, 42h
  3214                              <1>         ;jne	short NOT_VERF
  3215                              <1> 	;mov	edx, 0FF0000h
  3216                              <1> 	;jmp	short J33
  3217                              <1> ;NOT_VERF:
  3218                              <1> 	; 11/07/2022
  3219 000019A6 89EA                <1> 	mov	edx, ebp
  3220                              <1> 	;
  3221                              <1> 	;add	dx, cx			; check for (64K) overflow
  3222                              <1> 	; 18/07/2022
  3223                              <1> 	; (512 bytes/sector)
  3224 000019A8 6681C2FF01          <1> 	add	dx, 511 
  3225 000019AD 7239                <1> 	jc	short dma_bnd_err
  3226                              <1> 	;
  3227                              <1> 	;sub	dx, cx ; 11/07/2022	; Restore start address
  3228                              <1> J33:
  3229                              <1> 	; 08/07/2022
  3230 000019AF FA                  <1> 	cli				; DISABLE INTERRUPTS DURING DMA SET-UP
  3231 000019B0 E60C                <1> 	out	DMA+12, al		; SET THE FIRST/LAST F/F
  3232                              <1> 	IODELAY				; WAIT FOR I/O
  2130 000019B2 EB00                <2>  jmp short $+2
  2131 000019B4 EB00                <2>  jmp short $+2
  3233 000019B6 E60B                <1> 	out	DMA+11, al		; OUTPUT THE MODE BYTE
  3234                              <1> 	;mov	eax, edx		; Buffer address
  3235                              <1> 	; 11/07/2022
  3236 000019B8 89E8                <1> 	mov	eax, ebp ; buffer address
  3237 000019BA E604                <1> 	out	DMA+4, al		; OUTPUT LOW ADDRESS
  3238                              <1> 	IODELAY				; WAIT FOR I/O
  2130 000019BC EB00                <2>  jmp short $+2
  2131 000019BE EB00                <2>  jmp short $+2
  3239 000019C0 88E0                <1> 	mov	al, ah
  3240 000019C2 E604                <1> 	out	DMA+4, al		; OUTPUT HIGH ADDRESS
  3241 000019C4 C1E810              <1> 	shr	eax, 16
  3242                              <1> 	IODELAY				; I/O WAIT STATE
  2130 000019C7 EB00                <2>  jmp short $+2
  2131 000019C9 EB00                <2>  jmp short $+2
  3243 000019CB E681                <1> 	out	081h, al		; OUTPUT highest BITS TO PAGE REGISTER
  3244                              <1> 	IODELAY
  2130 000019CD EB00                <2>  jmp short $+2
  2131 000019CF EB00                <2>  jmp short $+2
  3245                              <1> 	;;mov	ax, cx			; Byte count - 1
  3246                              <1> 	;mov	al, cl
  3247                              <1> 	; 18/07/2022
  3248                              <1> 	; (Byte count - 1 = 511)
  3249 000019D1 B0FF                <1> 	mov	al, 0FFh ; 511-256
  3250 000019D3 E605                <1> 	out	DMA+5, al		; LOW BYTE OF COUNT
  3251                              <1> 	IODELAY				; WAIT FOR I/O
  2130 000019D5 EB00                <2>  jmp short $+2
  2131 000019D7 EB00                <2>  jmp short $+2
  3252                              <1> 	;;mov	al, ah
  3253                              <1> 	;mov	al, ch
  3254                              <1> 	; 18/07/2022
  3255 000019D9 B001                <1> 	mov	al, 1 ; 256
  3256 000019DB E605                <1> 	out	DMA+5, al		; HIGH BYTE OF COUNT
  3257                              <1> 	IODELAY
  2130 000019DD EB00                <2>  jmp short $+2
  2131 000019DF EB00                <2>  jmp short $+2
  3258 000019E1 FB                  <1> 	sti				; RE-ENABLE INTERRUPTS
  3259 000019E2 B002                <1> 	mov	al, 2			; MODE FOR 8237
  3260 000019E4 E60A                <1> 	out	DMA+10, al		; INITIALIZE THE DISKETTE CHANNEL
  3261                              <1> 	
  3262 000019E6 F8                  <1> 	clc	; 04/02/2016
  3263                              <1> 	
  3264 000019E7 C3                  <1> 	retn
  3265                              <1> 
  3266                              <1> 	; 18/07/2022
  3267                              <1> ;dma_bnd_err_stc:
  3268                              <1> ;	stc
  3269                              <1> 
  3270                              <1> dma_bnd_err:
  3271 000019E8 C605[BC610000]09    <1> 	mov	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3272 000019EF C3                  <1> 	retn				; CY SET BY ABOVE IF ERROR
  3273                              <1> 
  3274                              <1> ;-------------------------------------------------------------------------------
  3275                              <1> ; NEC_INIT	
  3276                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3277                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3278                              <1> ;
  3279                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3280                              <1> ;
  3281                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3282                              <1> ;-------------------------------------------------------------------------------
  3283                              <1> NEC_INIT:
  3284                              <1> 	; 11/07/2022
  3285                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3286                              <1> 	;push	ax			; SAVE NEC COMMAND
  3287                              <1> 	; 24/12/2021
  3288 000019F0 50                  <1> 	push	eax
  3289 000019F1 E886020000          <1> 	call	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3290                              <1> 
  3291                              <1> ;-----	DO THE SEEK OPERATION
  3292                              <1> 
  3293                              <1> 	;mov	ch, [ebp+1]		; CH = TRACK #
  3294                              <1> 	; 11/07/2022
  3295 000019F6 89F1                <1> 	mov	ecx, esi ; byte 2 = track, byte = 1 head, byte 0 = sector
  3296 000019F8 C1E908              <1> 	shr	ecx, 8
  3297                              <1> 	; ch = track #	
  3298                              <1> 
  3299 000019FB E86B030000          <1> 	call	SEEK			; MOVE TO CORRECT TRACK
  3300                              <1> 	;pop	ax			; RECOVER COMMAND
  3301                              <1> 	; 24/12/2021
  3302 00001A00 58                  <1> 	pop	eax
  3303 00001A01 721D                <1> 	jc	short ER_1		; ERROR ON SEEK
  3304 00001A03 BB[201A0000]        <1> 	mov	ebx, ER_1		; LOAD ERROR ADDRESS
  3305 00001A08 53                  <1> 	push	ebx			; PUSH NEC_OUT ERROR RETURN
  3306                              <1> 
  3307                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3308                              <1> 
  3309 00001A09 E824030000          <1> 	call	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3310 00001A0E 89F0                <1> 	mov	eax, esi		; AH = HEAD #
  3311 00001A10 89FB                <1> 	mov	ebx, edi		; BL = DRIVE #
  3312 00001A12 C0E402              <1> 	sal	ah, 2			; MOVE IT TO BIT 2
  3313 00001A15 80E404              <1> 	and	ah, 00000100b		; ISOLATE THAT BIT
  3314 00001A18 08DC                <1> 	or	ah, bl			; OR IN THE DRIVE NUMBER
  3315 00001A1A E813030000          <1> 	call	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  3316 00001A1F 5B                  <1> 	pop	ebx			; THROW AWAY ERROR RETURN
  3317                              <1> ER_1:
  3318 00001A20 C3                  <1> 	retn
  3319                              <1> 
  3320                              <1> ;-------------------------------------------------------------------------------
  3321                              <1> ; RWV_COM
  3322                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  3323                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  3324                              <1> ;
  3325                              <1> ; ON ENTRY:	EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  3326                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3327                              <1> ;-------------------------------------------------------------------------------
  3328                              <1> RWV_COM:
  3329                              <1> 	; 11/07/2022
  3330                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3331 00001A21 B8[6E1A0000]        <1> 	mov	eax, ER_2		; LOAD ERROR ADDRESS
  3332 00001A26 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  3333                              <1> 	;mov	ah, [ebp+1]		; OUTPUT TRACK #
  3334                              <1> 	; 11/07/2022
  3335 00001A27 89F0                <1> 	mov	eax, esi ; byte 0 = sector, byte 1 = head, byte 2 = track
  3336 00001A29 C1E808              <1> 	shr	eax, 8
  3337                              <1> 	; ah = track # 
  3338 00001A2C E801030000          <1> 	call	NEC_OUTPUT
  3339 00001A31 89F0                <1> 	mov	eax, esi		; OUTPUT HEAD #
  3340                              <1> 	; ah = head #
  3341 00001A33 E8FA020000          <1> 	call	NEC_OUTPUT
  3342                              <1>         ;mov	ah, [ebp]		; OUTPUT SECTOR #
  3343 00001A38 89F0                <1> 	mov	eax, esi
  3344 00001A3A 88C4                <1> 	mov	ah, al
  3345                              <1>  	; ah = sector #
  3346 00001A3C E8F1020000          <1> 	CALL	NEC_OUTPUT
  3347                              <1> 	;mov	dl, 3			; BYTES/SECTOR PARAMETER FROM BLOCK
  3348 00001A41 B003                <1> 	mov	al, 3 ; 08/07/2022
  3349 00001A43 E8F9010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3350 00001A48 E8E5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3351                              <1> 	;mov	dl, 4			; EOT PARAMETER FROM BLOCK
  3352 00001A4D B004                <1> 	mov	al, 4 ; 08/07/2022
  3353 00001A4F E8ED010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3354 00001A54 E8D9020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3355 00001A59 8A6305              <1>         mov	ah, [ebx+MD.GAP]	; GET GAP LENGTH
  3356                              <1> _R15:
  3357 00001A5C E8D1020000          <1> 	call	NEC_OUTPUT
  3358                              <1> 	;mov	dl, 6			; DTL PARAMETER PROM BLOCK
  3359 00001A61 B006                <1> 	mov	al, 6 ; 08/07/2022
  3360 00001A63 E8D9010000          <1> 	call	GET_PARM		; .. TO THE NEC
  3361 00001A68 E8C5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3362 00001A6D 58                  <1> 	pop	eax			; THROW AWAY ERROR EXIT
  3363                              <1> ER_2:
  3364 00001A6E C3                  <1> 	retn
  3365                              <1> 
  3366                              <1> ;-------------------------------------------------------------------------------
  3367                              <1> ; NEC_TERM
  3368                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  3369                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  3370                              <1> ;
  3371                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3372                              <1> ;-------------------------------------------------------------------------------
  3373                              <1> 
  3374                              <1> NEC_TERM:
  3375                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3376                              <1> 
  3377                              <1> ;-----	LET THE OPERATION HAPPEN
  3378                              <1> 
  3379 00001A6F 56                  <1> 	push	esi			; SAVE HEAD #, # OF SECTORS
  3380 00001A70 E8C7030000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  3381 00001A75 9C                  <1> 	pushfd	; 24/12/2021
  3382 00001A76 E8F0030000          <1> 	call	RESULTS			; GET THE NEC STATUS
  3383 00001A7B 724B                <1> 	jc	short SET_END_POP
  3384 00001A7D 9D                  <1> 	popfd	; 24/12/2021
  3385 00001A7E 723E                <1> 	jc	short SET_END		; LOOK FOR ERROR
  3386                              <1> 
  3387                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  3388                              <1> 
  3389 00001A80 FC                  <1> 	cld				; SET THE CORRECT DIRECTION
  3390 00001A81 BE[BD610000]        <1> 	mov	esi, NEC_STATUS		; POINT TO STATUS FIELD
  3391 00001A86 AC                  <1> 	lodsb				; GET ST0
  3392 00001A87 24C0                <1> 	and	al, 11000000b		; TEST FOR NORMAL TERMINATION
  3393 00001A89 7433                <1> 	jz	short SET_END
  3394 00001A8B 3C40                <1> 	cmp	al, 01000000b		; TEST FOR ABNORMAL TERMINATION
  3395 00001A8D 7527                <1> 	jnz	short J18		; NOT ABNORMAL, BAD NEC
  3396                              <1> 
  3397                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  3398                              <1> 
  3399 00001A8F AC                  <1> 	lodsb				; GET ST1
  3400 00001A90 D0E0                <1> 	sal	al, 1			; TEST FOR EDT FOUND
  3401 00001A92 B404                <1> 	mov	ah, RECORD_NOT_FND
  3402 00001A94 7222                <1> 	jc	short J19
  3403 00001A96 C0E002              <1> 	sal	al, 2
  3404 00001A99 B410                <1> 	mov	ah, BAD_CRC
  3405 00001A9B 721B                <1> 	jc	short J19
  3406 00001A9D D0E0                <1> 	sal	al, 1			; TEST FOR DMA OVERRUN
  3407 00001A9F B408                <1> 	mov	ah, BAD_DMA
  3408 00001AA1 7215                <1> 	jc	short J19
  3409 00001AA3 C0E002              <1> 	sal	al, 2			; TEST FOR RECORD NOT FOUND
  3410 00001AA6 B404                <1> 	mov	ah, RECORD_NOT_FND
  3411 00001AA8 720E                <1> 	jc	short J19
  3412 00001AAA D0E0                <1> 	sal	al, 1
  3413 00001AAC B403                <1> 	mov	ah, WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  3414 00001AAE 7208                <1> 	jc	short J19
  3415 00001AB0 D0E0                <1> 	sal	al, 1			; TEST MISSING ADDRESS MARK
  3416 00001AB2 B402                <1> 	mov	ah, BAD_ADDR_MARK
  3417 00001AB4 7202                <1> 	jc	short J19
  3418                              <1> 
  3419                              <1> ;----- 	NEC MUST HAVE FAILED
  3420                              <1> J18:
  3421 00001AB6 B420                <1> 	mov	ah, BAD_NEC
  3422                              <1> J19:
  3423 00001AB8 0825[BC610000]      <1> 	or	[DSKETTE_STATUS], ah
  3424                              <1> SET_END:
  3425 00001ABE 803D[BC610000]01    <1> 	cmp	byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION
  3426 00001AC5 F5                  <1> 	cmc
  3427 00001AC6 5E                  <1> 	pop	esi
  3428 00001AC7 C3                  <1> 	retn				; RESTORE HEAD #, # OF SECTORS
  3429                              <1> 
  3430                              <1> SET_END_POP:
  3431 00001AC8 9D                  <1> 	popfd	; 24/12/2021
  3432 00001AC9 EBF3                <1> 	jmp	short SET_END
  3433                              <1> 
  3434                              <1> ;-------------------------------------------------------------------------------
  3435                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  3436                              <1> ;-------------------------------------------------------------------------------
  3437                              <1> DSTATE:
  3438                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3439 00001ACB 803D[BC610000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3440 00001AD2 753E                <1> 	jne	short SETBAC		; IF ERROR JUMP
  3441 00001AD4 808F[C7610000]10    <1> 	or	byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  3442 00001ADB F687[C7610000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ?
  3443 00001AE2 752E                <1> 	jnz	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  3444 00001AE4 8A87[C7610000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3445 00001AEA 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3446 00001AEC 3C80                <1> 	cmp	al, RATE_250		; RATE 250 ?
  3447 00001AEE 751B                <1> 	jne	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  3448                              <1> 
  3449                              <1> ;----- 	CHECK IF IT IS 1.44M
  3450                              <1> 
  3451 00001AF0 E843010000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3452                              <1> 	;;20/02/2015
  3453                              <1> 	;;jc	short M_12		; CMOS BAD
  3454 00001AF5 7414                <1> 	jz	short M_12 ;; 20/02/2015
  3455 00001AF7 3C04                <1> 	cmp	al, 4			; 1.44MB DRIVE ?
  3456 00001AF9 7410                <1> 	je	short M_12		; YES
  3457                              <1> M_720:
  3458 00001AFB 80A7[C7610000]FD    <1> 	and	byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  3459 00001B02 808F[C7610000]04    <1> 	or	byte [DSK_STATE+edi], DRV_DET  ; MARK DRIVE DETERMINED
  3460 00001B09 EB07                <1> 	jmp	short SETBAC		; BACK
  3461                              <1> M_12:	
  3462 00001B0B 808F[C7610000]06    <1> 	or	byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 
  3463                              <1> 					; TURN ON DETERMINED & FMT CAPA
  3464                              <1> SETBAC:
  3465 00001B12 C3                  <1> 	retn
  3466                              <1> 
  3467                              <1> ;-------------------------------------------------------------------------------
  3468                              <1> ; RETRY	
  3469                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  3470                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  3471                              <1> ;
  3472                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  3473                              <1> ;-------------------------------------------------------------------------------
  3474                              <1> RETRY:
  3475                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3476 00001B13 803D[BC610000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION
  3477 00001B1A 7444                <1> 	je	short NO_RETRY		; SUCCESSFUL OPERATION
  3478 00001B1C 803D[BC610000]80    <1> 	cmp	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY
  3479 00001B23 743B                <1> 	je	short NO_RETRY
  3480 00001B25 8AA7[C7610000]      <1> 	mov	ah, [DSK_STATE+edi]	; GET MEDIA STATE OF DRIVE
  3481 00001B2B F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED/DETERMINED ?
  3482 00001B2E 7530                <1> 	jnz	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  3483 00001B30 80E4C0              <1> 	and	ah, RATE_MSK		; ISOLATE RATE
  3484 00001B33 8A2D[C4610000]      <1> 	mov	ch, [LASTRATE]		; GET START OPERATION STATE
  3485 00001B39 C0C504              <1> 	rol	ch, 4			; TO CORRESPONDING BITS
  3486 00001B3C 80E5C0              <1> 	and	ch, RATE_MSK		; ISOLATE RATE BITS
  3487 00001B3F 38E5                <1> 	cmp	ch, ah			; ALL RATES TRIED
  3488 00001B41 741D                <1> 	je	short NO_RETRY		; IF YES, THEN TRUE ERROR
  3489                              <1> 
  3490                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  3491                              <1> ;	 00000000B (500) -> 10000000B	(250)
  3492                              <1> ;	 10000000B (250) -> 01000000B	(300)
  3493                              <1> ;	 01000000B (300) -> 00000000B	(500)
  3494                              <1> 
  3495 00001B43 80FC01              <1> 	cmp	ah, RATE_500+1		; SET CY FOR RATE 500
  3496 00001B46 D0DC                <1> 	rcr	ah, 1			; TO NEXT STATE
  3497 00001B48 80E4C0              <1> 	and	ah, RATE_MSK		; KEEP ONLY RATE BITS
  3498 00001B4B 80A7[C7610000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP)
  3499                              <1> 					; RATE, DBL STEP OFF
  3500 00001B52 08A7[C7610000]      <1> 	or	[DSK_STATE+edi], ah	; TURN ON NEW RATE
  3501 00001B58 C605[BC610000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY
  3502 00001B5F F9                  <1> 	stc				; SET CARRY FOR RETRY
  3503                              <1> NO_RETRY:	; 08/07/2022
  3504 00001B60 C3                  <1> 	retn				; RETRY RETURN
  3505                              <1> 
  3506                              <1> ;NO_RETRY:
  3507                              <1> 	;clc				; CLEAR CARRY NO RETRY
  3508                              <1> 	;RETn				; NO RETRY RETURN
  3509                              <1> 
  3510                              <1> ;-------------------------------------------------------------------------------
  3511                              <1> ; NUM_TRANS
  3512                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  3513                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  3514                              <1> ;
  3515                              <1> ; ON ENTRY:	[BP+1] = TRACK
  3516                              <1> ;		SI-HI  = HEAD
  3517                              <1> ;		[BP]   = START SECTOR
  3518                              <1> ;
  3519                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  3520                              <1> ;-------------------------------------------------------------------------------
  3521                              <1> NUM_TRANS:
  3522                              <1> 	; 11/07/2022
  3523                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3524 00001B61 30C0                <1> 	xor	al, al			; CLEAR FOR ERROR
  3525 00001B63 803D[BC610000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3526                              <1> 	; 24/12/2021
  3527 00001B6A 7529                <1> 	jne	short NT_OUT		; IF ERROR 0 TRANSFERRED
  3528                              <1> 	;mov	dl, 4			; SECTORS/TRACK OFFSET TO DL
  3529 00001B6C B004                <1> 	mov	al, 4 ; 08/07/2022
  3530 00001B6E E8CE000000          <1> 	call	GET_PARM		; AH = SECTORS/TRACK
  3531                              <1> 	;mov	bl, [NEC_STATUS+5]	; GET ENDING SECTOR
  3532 00001B73 A0[C2610000]        <1> 	mov	al, [NEC_STATUS+5]
  3533 00001B78 89F1                <1> 	mov	ecx, esi		; CH = HEAD # STARTED
  3534 00001B7A 88CB                <1> 	mov	bl, cl ; 11/07/2022 ; sector #
  3535 00001B7C 3A2D[C1610000]      <1> 	cmp	ch, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  3536 00001B82 750D                <1> 	jne	short DIF_HD		; IF ON SAME HEAD, THEN NO ADJUST
  3537                              <1> 	; 11/07/2022
  3538                              <1> 	;mov	ch, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  3539                              <1> 	;cmp	ch, [ebp+1]		; IS IT ASKED FOR TRACK
  3540                              <1> 	;jz	short SAME_TR		; IF SAME TRACK NO INCREASE
  3541 00001B84 C1E908              <1> 	shr	ecx, 8 ; byte 3 = track # --> byte 2
  3542 00001B87 3A2D[C0610000]      <1> 	cmp	ch, [NEC_STATUS+3]
  3543 00001B8D 7404                <1> 	je	short SAME_TRK		
  3544                              <1> 	; 11/07/2022
  3545                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3546 00001B8F 00E0                <1> 	add	al, ah
  3547                              <1> DIF_HD:
  3548                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3549 00001B91 00E0                <1> 	add	al, ah
  3550                              <1> SAME_TRK:
  3551                              <1> 	;sub	bl, [ebp]		; SUBTRACT START FROM END
  3552                              <1> 	;mov	al, bl			; TO AL
  3553 00001B93 28D8                <1> 	sub	al, bl
  3554                              <1> NT_OUT:
  3555 00001B95 C3                  <1> 	retn
  3556                              <1> 
  3557                              <1> ;-------------------------------------------------------------------------------
  3558                              <1> ; SETUP_DBL
  3559                              <1> ;	CHECK DOUBLE STEP.
  3560                              <1> ;
  3561                              <1> ; ON ENTRY :	EDI = DRIVE #
  3562                              <1> ;
  3563                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  3564                              <1> ;-------------------------------------------------------------------------------
  3565                              <1> SETUP_DBL:
  3566                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3567 00001B96 8AA7[C7610000]      <1> 	mov	ah, [DSK_STATE+edi]	; ACCESS STATE
  3568 00001B9C F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED STATE ?
  3569 00001B9F 7578                <1> 	jnz	short NO_DBL		; IF ESTABLISHED THEN DOUBLE DONE
  3570                              <1> 
  3571                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  3572                              <1> 
  3573 00001BA1 C605[B9610000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  3574 00001BA8 E8CF000000          <1> 	call	MOTOR_ON		; ENSURE MOTOR STAY ON
  3575 00001BAD B500                <1> 	mov	ch, 0			; LOAD TRACK 0
  3576 00001BAF E8B7010000          <1> 	call	SEEK			; SEEK TO TRACK 0
  3577 00001BB4 E862000000          <1> 	call	READ_ID			; READ ID FUNCTION
  3578 00001BB9 7243                <1> 	jc	short SD_ERR		; IF ERROR NO TRACK 0
  3579                              <1> 
  3580                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  3581                              <1> 
  3582 00001BBB 66B95004            <1> 	mov	cx, 0450h 		; START, MAX TRACKS
  3583 00001BBF F687[C7610000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  3584 00001BC6 7402                <1> 	jz	short CNT_OK		; IF NOT COUNT IS SETUP
  3585 00001BC8 B1A0                <1> 	mov	cl, 0A0h		; MAXIMUM TRACK 1.2 MB
  3586                              <1> 
  3587                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  3588                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  3589                              <1> ;	THEN SET DOUBLE STEP ON.
  3590                              <1> 
  3591                              <1> CNT_OK:
  3592 00001BCA C605[BB610000]FF    <1>        	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 
  3593                              <1> 	; 24/12/2021
  3594 00001BD1 51                  <1> 	push	ecx			; SAVE TRACK, COUNT
  3595 00001BD2 C605[BC610000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS
  3596 00001BD9 31C0                <1> 	xor	eax, eax		; CLEAR EAX
  3597 00001BDB D0ED                <1> 	shr	ch, 1			; HALVE TRACK, CY = HEAD
  3598 00001BDD C0D003              <1> 	rcl	al, 3			; AX = HEAD IN CORRECT BIT
  3599                              <1> 	; 24/12/2021
  3600 00001BE0 50                  <1> 	push	eax			; SAVE HEAD
  3601 00001BE1 E885010000          <1> 	call	SEEK			; SEEK TO TRACK
  3602                              <1> 	; 24/12/2021
  3603 00001BE6 58                  <1> 	pop	eax			; RESTORE HEAD
  3604 00001BE7 09C7                <1> 	or	edi, eax		; DI = HEAD OR'ED DRIVE
  3605 00001BE9 E82D000000          <1> 	call	READ_ID			; READ ID HEAD 0
  3606 00001BEE 9C                  <1> 	pushf				; SAVE RETURN FROM READ_ID
  3607 00001BEF 6681E7FB00          <1> 	and	di, 11111011b		; TURN OFF HEAD 1 BIT
  3608 00001BF4 9D                  <1> 	popf				; RESTORE ERROR RETURN
  3609                              <1> 	; 24/12/2021
  3610 00001BF5 59                  <1> 	pop	ecx			; RESTORE COUNT
  3611 00001BF6 7308                <1> 	jnc	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  3612 00001BF8 FEC5                <1> 	inc	ch			; INC FOR NEXT TRACK
  3613 00001BFA 38CD                <1> 	cmp	ch, cl			; REACHED MAXIMUM YET
  3614 00001BFC 75CC                <1> 	jnz	short CNT_OK		; CONTINUE TILL ALL TRIED
  3615                              <1> 
  3616                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  3617                              <1> 
  3618                              <1> SD_ERR:	
  3619 00001BFE F9                  <1> 	stc				; SET CARRY FOR ERROR
  3620 00001BFF C3                  <1> 	retn				; SETUP_DBL ERROR EXIT
  3621                              <1> 
  3622                              <1> DO_CHK:
  3623 00001C00 8A0D[C0610000]      <1> 	mov	cl, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  3624 00001C06 888F[C9610000]      <1> 	mov	[DSK_TRK+edi], cl	; STORE TRACK NUMBER
  3625 00001C0C D0ED                <1> 	shr	ch, 1			; HALVE TRACK
  3626 00001C0E 38CD                <1> 	cmp	ch, cl			; IS IT THE SAME AS ASKED FOR TRACK
  3627 00001C10 7407                <1> 	jz	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  3628 00001C12 808F[C7610000]20    <1> 	or	byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  3629                              <1> NO_DBL:
  3630 00001C19 F8                  <1> 	clc				; CLEAR ERROR FLAG
  3631 00001C1A C3                  <1> 	retn
  3632                              <1> 
  3633                              <1> ;-------------------------------------------------------------------------------
  3634                              <1> ; READ_ID
  3635                              <1> ;	READ ID FUNCTION.
  3636                              <1> ;
  3637                              <1> ; ON ENTRY:	EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  3638                              <1> ;
  3639                              <1> ; ON EXIT: 	EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  3640                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3641                              <1> ;-------------------------------------------------------------------------------
  3642                              <1> READ_ID:
  3643                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3644 00001C1B B8[371C0000]        <1> 	mov	eax, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  3645 00001C20 50                  <1> 	push	eax
  3646 00001C21 B44A                <1> 	mov	ah, 4Ah			; READ ID COMMAND
  3647 00001C23 E80A010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3648 00001C28 89F8                <1> 	mov	eax, edi		; DRIVE # TO AH, HEAD 0
  3649 00001C2A 88C4                <1> 	mov	ah, al
  3650 00001C2C E801010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3651 00001C31 E839FEFFFF          <1> 	call	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  3652 00001C36 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3653                              <1> ER_3:
  3654 00001C37 C3                  <1> 	retn
  3655                              <1> 
  3656                              <1> ;-------------------------------------------------------------------------------
  3657                              <1> ; CMOS_TYPE
  3658                              <1> ;	RETURNS CMOS DISKETTE TYPE
  3659                              <1> ;
  3660                              <1> ; ON ENTRY:	EDI = DRIVE #
  3661                              <1> ;
  3662                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  3663                              <1> ;-------------------------------------------------------------------------------
  3664                              <1> 
  3665                              <1> CMOS_TYPE: ; 11/12/2014
  3666                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3667 00001C38 8A87[5C5C0000]      <1> 	mov	al, [edi+fd0_type] ; diskette type
  3668 00001C3E 20C0                <1> 	and 	al, al ; 18/12/2014
  3669 00001C40 C3                  <1> 	retn
  3670                              <1> 
  3671                              <1> ;-------------------------------------------------------------------------------
  3672                              <1> ; GET_PARM
  3673                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  3674                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  3675                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  3676                              <1> ;	THE PARAMETER IN DL.
  3677                              <1> ;
  3678                              <1> ; ON ENTRY:	AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022
  3679                              <1> ;
  3680                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  3681                              <1> ;		AL DESTROYED
  3682                              <1> ;-------------------------------------------------------------------------------
  3683                              <1> GET_PARM:
  3684                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3685                              <1> 	;	 ENTRY:
  3686                              <1> 	;	     AL = INDEX
  3687                              <1> 	;	    EDI = DRIVE #
  3688                              <1> 	; 	 RETURN:
  3689                              <1> 	;	     AH = REQUESTED PARAMETER
  3690                              <1> 	;	     AL DESTROYED
  3691                              <1> 	
  3692                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3693                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  3694                              <1> 	;push	esi ; 11/07/2022
  3695 00001C41 53                  <1> 	push	ebx			; SAVE EBX	
  3696 00001C42 0FB6D8              <1> 	movzx	ebx, al			; EBX = INDEX
  3697                              <1>    	; 17/12/2014
  3698                              <1> 	;mov	ax, [cfd] ; current (AL) and previous fd (AH)
  3699                              <1> 	; 11/07/2022
  3700                              <1> 	;cmp	al, ah
  3701                              <1> 	;je	short gpndc
  3702                              <1> 
  3703                              <1> 	; 11/07/2022
  3704 00001C45 89F8                <1> 	mov	eax, edi
  3705 00001C47 3A05[515C0000]      <1> 	cmp	al, [pfd] ; is same with previous drive # ?
  3706 00001C4D 7423                <1> 	je	short gpndc	
  3707                              <1> 
  3708 00001C4F A2[515C0000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  3709                              <1> 
  3710 00001C54 53                  <1> 	push	ebx ; 08/02/2015
  3711                              <1> 	
  3712                              <1> 	;mov	bl, al 
  3713                              <1> 	; 11/12/2014
  3714                              <1> 	;mov	al, [ebx+fd0_type]	; Drive type (0,1,2,3,4)
  3715                              <1> 	; 11/07/2022
  3716 00001C55 8A87[5C5C0000]      <1> 	mov	al, [edi+fd0_type]	; Drive type (0,1,2,3,4)	
  3717                              <1> 	; 18/12/2014
  3718 00001C5B 20C0                <1> 	and	al, al
  3719 00001C5D 7507                <1> 	jnz	short gpdtc
  3720 00001C5F BB[3B5C0000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  3721 00001C64 EB05                <1>         jmp     short gpdpu
  3722                              <1> gpdtc:	
  3723 00001C66 E8AEFBFFFF          <1> 	call	DR_TYPE_CHECK
  3724                              <1> 	; cf = 1 -> EBX points to 1.44MB fd parameter table (default)
  3725                              <1> gpdpu:
  3726 00001C6B 891D[D85B0000]      <1> 	mov	[DISK_POINTER], ebx
  3727 00001C71 5B                  <1> 	pop	ebx
  3728                              <1> gpndc:
  3729                              <1> 	;mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  3730                              <1> 	;mov	ah, [esi+ebx]		; GET THE WORD
  3731                              <1> 	; 11/07/2022
  3732 00001C72 031D[D85B0000]      <1> 	add	ebx, [DISK_POINTER]
  3733 00001C78 8A23                <1> 	mov	ah, [ebx] 
  3734 00001C7A 5B                  <1> 	pop	ebx			; RESTORE EBX
  3735                              <1> 	;pop	esi ; 11/07/2022
  3736 00001C7B C3                  <1> 	retn
  3737                              <1> 
  3738                              <1> ;-------------------------------------------------------------------------------
  3739                              <1> ; MOTOR_ON
  3740                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  3741                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  3742                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  3743                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  3744                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  3745                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  3746                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  3747                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  3748                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  3749                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  3750                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  3751                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  3752                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  3753                              <1> ;
  3754                              <1> ; ON ENTRY:	EDI = DRIVE #
  3755                              <1> ; ON EXIT:	EAX, ECX, EDX DESTROYED
  3756                              <1> ;-------------------------------------------------------------------------------
  3757                              <1> MOTOR_ON:
  3758                              <1> 	; 12/07/2022
  3759                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3760 00001C7C 53                  <1> 	push	ebx			; SAVE REG.
  3761 00001C7D E820000000          <1> 	call	TURN_ON			; TURN ON MOTOR
  3762 00001C82 721C                <1> 	jc	short MOT_IS_ON		; IF CY=1 NO WAIT
  3763                              <1> 	;call	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3764                              <1> 	; 08/07/2022
  3765                              <1> 	;call	XLAT_NEW ; 12/07/2022	; TRANSLATE STATE TO PRESENT ARCH,
  3766                              <1> 	;call	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  3767                              <1> 	;jc	short MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  3768                              <1> M_WAIT:
  3769                              <1> 	;mov	dl,10			; GET THE MOTOR WAIT PARAMETER
  3770 00001C84 B00A                <1> 	mov	al, 10 ; 08/07/2022
  3771 00001C86 E8B6FFFFFF          <1> 	call	GET_PARM
  3772                              <1> 	; 08/07/2022			; AH = MOTOR WAIT PARAMETER
  3773 00001C8B 80FC08              <1> 	cmp	ah, 8			; SEE IF AT LEAST A SECOND IS SPECIFIED			
  3774                              <1> 	;jae	short GP2		; IF YES, CONTINUE
  3775 00001C8E 7302                <1> 	jae	short J13
  3776 00001C90 B408                <1> 	mov	ah, 8			; ONE SECOND WAIT FOR MOTOR START UP
  3777                              <1> 
  3778                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  3779                              <1> GP2:	
  3780                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  3781                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  3782 00001C92 B95E200000          <1> 	mov	ecx, 8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  3783 00001C97 E810F7FFFF          <1> 	call	WAITF			; GO TO FIXED WAIT ROUTINE
  3784                              <1> 	;dec	al			; DECREMENT TIME VALUE
  3785 00001C9C FECC                <1> 	dec	ah
  3786 00001C9E 75F2                <1> 	jnz	short J13		; ARE WE DONE YET
  3787                              <1> MOT_IS_ON:
  3788 00001CA0 5B                  <1> 	pop	ebx			; RESTORE REG.
  3789 00001CA1 C3                  <1> 	retn
  3790                              <1> 
  3791                              <1> ;-------------------------------------------------------------------------------
  3792                              <1> ; TURN_ON
  3793                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  3794                              <1> ;
  3795                              <1> ; ON ENTRY:	EDI = DRIVE #
  3796                              <1> ;
  3797                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  3798                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  3799                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  3800                              <1> ;-------------------------------------------------------------------------------
  3801                              <1> TURN_ON:
  3802                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3803 00001CA2 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  3804 00001CA4 88D9                <1> 	mov	cl, bl			; CL = DRIVE #
  3805 00001CA6 C0C304              <1> 	rol	bl, 4			; BL = DRIVE SELECT
  3806 00001CA9 FA                  <1> 	cli				; NO INTERRUPTS WHILE DETERMINING STATUS
  3807 00001CAA C605[BB610000]FF    <1> 	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION
  3808 00001CB1 A0[BA610000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3809 00001CB6 2430                <1> 	and	al, 00110000b		; KEEP ONLY DRIVE SELECT BITS
  3810 00001CB8 B401                <1> 	mov	ah, 1			; MASK FOR DETERMINING MOTOR BIT
  3811 00001CBA D2E4                <1> 	shl	ah, cl			; AH = MOTOR ON, A=00000001, B=00000010
  3812                              <1> 
  3813                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  3814                              <1> ;  BL = DRIVE SELECT DESIRED
  3815                              <1> ;  AH = MOTOR ON MASK DESIRED
  3816                              <1> 
  3817 00001CBC 38D8                <1> 	cmp	al, bl			; REQUESTED DRIVE ALREADY SELECTED ?
  3818 00001CBE 7508                <1> 	jne	short TURN_IT_ON	; IF NOT SELECTED JUMP
  3819 00001CC0 8425[BA610000]      <1> 	test	ah, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  3820 00001CC6 7535                <1> 	jnz	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  3821                              <1> 
  3822                              <1> TURN_IT_ON:
  3823 00001CC8 08DC                <1> 	or	ah, bl			; AH = DRIVE SELECT AND MOTOR ON
  3824 00001CCA 8A3D[BA610000]      <1> 	mov	bh, [MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  3825 00001CD0 80E70F              <1> 	and	bh, 00001111b		; KEEP ONLY MOTOR BITS
  3826 00001CD3 8025[BA610000]CF    <1> 	and	byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT
  3827 00001CDA 0825[BA610000]      <1> 	or	[MOTOR_STATUS], ah	; OR IN DRIVE SELECTED AND MOTOR ON
  3828 00001CE0 A0[BA610000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3829 00001CE5 88C3                <1> 	mov	bl, al			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  3830 00001CE7 80E30F              <1> 	and	bl, 00001111b		; KEEP ONLY MOTOR BITS
  3831 00001CEA FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3832 00001CEB 243F                <1> 	and	al, 00111111b		; STRIP AWAY UNWANTED BITS
  3833 00001CED C0C004              <1> 	rol	al, 4			; PUT BITS IN DESIRED POSITIONS
  3834 00001CF0 0C0C                <1> 	or	al, 00001100b		; NO RESET, ENABLE DMA/INTERRUPT
  3835 00001CF2 66BAF203            <1> 	mov	dx, 03F2h		; SELECT DRIVE AND TURN ON MOTOR
  3836 00001CF6 EE                  <1> 	out	dx, al
  3837 00001CF7 38FB                <1> 	cmp	bl, bh			; NEW MOTOR TURNED ON ?
  3838                              <1> 	;je	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  3839 00001CF9 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  3840 00001CFB F8                  <1> 	clc				; RESET CARRY MEANING WAIT
  3841 00001CFC C3                  <1> 	retn
  3842                              <1> 
  3843                              <1> NO_MOT_WAIT:
  3844 00001CFD FB                  <1> 	sti
  3845                              <1> no_mot_w1: ; 27/02/2015
  3846 00001CFE F9                  <1> 	stc				; SET NO WAIT REQUIRED
  3847                              <1> 	;sti				; INTERRUPTS BACK ON
  3848 00001CFF C3                  <1> 	retn
  3849                              <1> 
  3850                              <1> ;-------------------------------------------------------------------------------
  3851                              <1> ; HD_WAIT
  3852                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  3853                              <1> ;
  3854                              <1> ; ON ENTRY:	DI = DRIVE #
  3855                              <1> ;
  3856                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  3857                              <1> ;-------------------------------------------------------------------------------
  3858                              <1> HD_WAIT:
  3859                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3860                              <1> 	;mov	dl, 9			; GET HEAD SETTLE PARAMETER
  3861 00001D00 B009                <1> 	mov	al, 9	; 08/07/2022
  3862 00001D02 E83AFFFFFF          <1> 	CALL	GET_PARM
  3863 00001D07 08E4                <1> 	or	ah, ah	; 17/12/2014	; CHECK FOR ANY WAIT?
  3864 00001D09 7519                <1> 	jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3865 00001D0B F605[BA610000]80    <1>         test	byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION
  3866                              <1> 	;jz	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  3867                              <1> 	;or	ah, ah			; CHECK FOR ANY WAIT?
  3868                              <1> 	;jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3869 00001D12 741D                <1> 	jz	short HW_DONE
  3870 00001D14 B40F                <1> 	mov	ah, HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  3871 00001D16 8A87[C7610000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3872 00001D1C 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3873 00001D1E 3C80                <1> 	cmp	al, RATE_250		; 1.2 M DRIVE ?
  3874 00001D20 7502                <1> 	jnz	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  3875                              <1> ;GP3:
  3876 00001D22 B414                <1> 	mov	ah, HD320_SETTLE		; USE 320/360 HEAD SETTLE
  3877                              <1> ;	jmp	short DO_WAT
  3878                              <1> 
  3879                              <1> ;ISNT_WRITE:
  3880                              <1> ;	or	ah, ah			; CHECK FOR NO WAIT
  3881                              <1> ;	jz	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  3882                              <1> 
  3883                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  3884                              <1> DO_WAT:
  3885                              <1> ;	mov	al, ah			; AL = # MILLISECONDS
  3886                              <1> ;	;xor	ah, ah			; AX = # MILLISECONDS
  3887                              <1> J29:					; 	1 MILLISECOND LOOP
  3888                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  3889                              <1> 	;mov	ecx, 66			; COUNT AT 15.085737 US PER COUNT
  3890                              <1> 	; 08/07/2022
  3891 00001D24 29C9                <1> 	sub	ecx, ecx
  3892 00001D26 B142                <1> 	mov	cl, 66
  3893 00001D28 E87FF6FFFF          <1> 	call	WAITF			; DELAY FOR 1 MILLISECOND
  3894                              <1> 	;dec	al			; DECREMENT THE COUNT
  3895 00001D2D FECC                <1> 	dec	ah
  3896 00001D2F 75F3                <1> 	jnz	short J29		; DO AL MILLISECOND # OF TIMES
  3897                              <1> HW_DONE:
  3898 00001D31 C3                  <1> 	retn
  3899                              <1> 
  3900                              <1> ;-------------------------------------------------------------------------------
  3901                              <1> ; NEC_OUTPUT
  3902                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  3903                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  3904                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  3905                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  3906                              <1> ; 
  3907                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  3908                              <1> ;
  3909                              <1> ; ON EXIT:	CY = 0  SUCCESS
  3910                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  3911                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  3912                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  3913                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  3914                              <1> ;
  3915                              <1> ;		EAX, ECX, EDX DESTROYED
  3916                              <1> ;-------------------------------------------------------------------------------
  3917                              <1> 
  3918                              <1> ; 09/12/2014 [Erdogan Tan] 
  3919                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  3920                              <1> ; Diskette Drive Controller Status Register (3F4h)
  3921                              <1> ;	This read only register facilitates the transfer of data between
  3922                              <1> ;	the system microprocessor and the controller.
  3923                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  3924                              <1> ;	  with the system micrprocessor.
  3925                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  3926                              <1> ;	  the transfer is to the controller.
  3927                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  3928                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  3929                              <1> ; Bit 3 - Reserved.
  3930                              <1> ; Bit 2 - Reserved.
  3931                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3932                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3933                              <1> 
  3934                              <1> ; Data Register (3F5h)
  3935                              <1> ; This read/write register passes data, commands and parameters, and provides
  3936                              <1> ; diskette status information.
  3937                              <1>   		
  3938                              <1> NEC_OUTPUT:
  3939                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3940                              <1> 	;push	ebx			; SAVE REG.
  3941 00001D32 BAF4030000          <1> 	mov	edx, 03F4h		; STATUS PORT
  3942                              <1> 	;xor	ecx, ecx		; COUNT FOR TIME OUT
  3943                              <1> 	; 16/12/2014
  3944                              <1> 	; waiting for (max.) 0.5 seconds
  3945                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  3946                              <1> 	;
  3947                              <1> 	; 17/12/2014
  3948                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  3949                              <1> 	;
  3950                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  3951                              <1> 	;		go on.
  3952                              <1> 	;INPUT:
  3953                              <1> 	;	AH=Mask for isolation bits.
  3954                              <1> 	;	AL=pattern to look for.
  3955                              <1> 	;	DX=Port to test for
  3956                              <1> 	;	ECX=Number of memory refresh periods to delay.
  3957                              <1> 	;	     (normally 30 microseconds per period.)
  3958                              <1> 	;
  3959                              <1> 	;WFP_SHORT:  
  3960                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  3961                              <1> 	;
  3962                              <1> 
  3963 00001D37 B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  3964                              <1> ;
  3965                              <1> ;WFPS_OUTER_LP:
  3966                              <1> ;	;
  3967                              <1> ;WFPS_CHECK_PORT:
  3968                              <1> J23:
  3969 00001D3C EC                  <1> 	in	al, dx			; GET STATUS
  3970 00001D3D 24C0                <1> 	and	al, 11000000b		; KEEP STATUS AND DIRECTION
  3971 00001D3F 3C80                <1> 	cmp	al, 10000000b		; STATUS 1 AND DIRECTION 0 ?
  3972 00001D41 7418                <1> 	jz	short J27		; STATUS AND DIRECTION OK
  3973                              <1> WFPS_HI:
  3974 00001D43 E461                <1> 	in	al, PORT_B	; 061h	; SYS1	; wait for hi to lo
  3975 00001D45 A810                <1> 	test	al, 010h		; transition on memory
  3976 00001D47 75FA                <1> 	jnz	short WFPS_HI		; refresh.
  3977                              <1> WFPS_LO:
  3978 00001D49 E461                <1> 	in	al, PORT_B		; SYS1
  3979 00001D4B A810                <1> 	test	al, 010h
  3980 00001D4D 74FA                <1> 	jz	short WFPS_LO
  3981                              <1> 	;loop	short WFPS_CHECK_PORT
  3982 00001D4F E2EB                <1> 	loop	J23	; 27/02/2015	; REPEAT TILL DELAY FINISHED
  3983                              <1> 
  3984                              <1> 	; fail
  3985                              <1> 
  3986                              <1> ;WFPS_TIMEOUT:
  3987                              <1> 
  3988                              <1> ;-----	FALL THRU TO ERROR RETURN
  3989                              <1> 
  3990 00001D51 800D[BC610000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  3991                              <1> 	;pop	ebx			; RESTORE REG.
  3992 00001D58 58                  <1> 	pop	eax ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  3993 00001D59 F9                  <1> 	stc				; INDICATE ERROR TO CALLER
  3994 00001D5A C3                  <1> 	retn
  3995                              <1> 
  3996                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  3997                              <1> 
  3998                              <1> J27:	
  3999 00001D5B 88E0                <1> 	mov	al, ah			; GET BYTE TO OUTPUT
  4000 00001D5D 42                  <1> 	inc	edx			; DATA PORT = STATUS PORT + 1
  4001 00001D5E EE                  <1> 	out	dx, al			; OUTPUT THE BYTE
  4002                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4003                              <1> 	; 27/02/2015
  4004 00001D5F 9C                  <1> 	pushfd	; 24/12/2021		; SAVE FLAGS
  4005                              <1> 	;mov	ecx, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4006 00001D60 29C9                <1> 	sub	ecx, ecx
  4007 00001D62 B103                <1> 	mov	cl, 3 ; 24/12/2021
  4008 00001D64 E843F6FFFF          <1> 	call 	WAITF			; NEC FLAGS UPDATE CYCLE
  4009 00001D69 9D                  <1> 	popfd	; 24/12/2021		; RESTORE FLAGS FOR EXIT
  4010                              <1> 	;pop	ebx			; RESTORE REG
  4011 00001D6A C3                  <1> 	retn				; CY = 0 FROM TEST INSTRUCTION
  4012                              <1> 
  4013                              <1> ;-------------------------------------------------------------------------------
  4014                              <1> ; SEEK
  4015                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4016                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4017                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4018                              <1> ;
  4019                              <1> ; ON ENTRY:	EDI = DRIVE #
  4020                              <1> ;		CH = TRACK #
  4021                              <1> ;
  4022                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4023                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4024                              <1> ;-------------------------------------------------------------------------------
  4025                              <1> SEEK:
  4026                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4027 00001D6B 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4028 00001D6D B001                <1> 	mov	al, 1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4029 00001D6F 86CB                <1> 	xchg	cl, bl			; SET DRIVE VALUE INTO CL
  4030 00001D71 D2C0                <1> 	rol	al, cl			; SHIFT MASK BY THE DRIVE VALUE
  4031 00001D73 86CB                <1> 	xchg	cl, bl			; RECOVER DRIVE VALUE
  4032 00001D75 8405[B9610000]      <1> 	test	al, [SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4033 00001D7B 7526                <1> 	jnz	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4034                              <1> 
  4035 00001D7D 0805[B9610000]      <1> 	or	[SEEK_STATUS], al	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4036 00001D83 E862000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4037 00001D88 730E                <1> 	jnc	short AFT_RECAL		; RECALIBRATE DONE
  4038                              <1> 
  4039                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4040                              <1> 
  4041 00001D8A C605[BC610000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS
  4042 00001D91 E854000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4043 00001D96 7251                <1> 	jc	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4044                              <1> 
  4045                              <1> AFT_RECAL:
  4046 00001D98 C687[C9610000]00    <1> 	mov	byte [DSK_TRK+edi], 0	; SAVE NEW CYLINDER AS PRESENT POSITION
  4047 00001D9F 08ED                <1> 	or	ch, ch			; CHECK FOR SEEK TO TRACK 0
  4048 00001DA1 743F                <1> 	jz	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4049                              <1> 
  4050                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4051                              <1> 
  4052 00001DA3 F687[C7610000]20    <1> J28A:	test	byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4053 00001DAA 7402                <1> 	jz	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4054 00001DAC D0E5                <1> 	shl	ch, 1			; DOUBLE NUMBER OF STEP TO TAKE
  4055                              <1> 
  4056 00001DAE 3AAF[C9610000]      <1> _R7:	cmp	ch, [DSK_TRK+edi]	; SEE IF ALREADY AT THE DESIRED TRACK
  4057 00001DB4 7433                <1> 	je	short RB		; IF YES, DO NOT NEED TO SEEK
  4058                              <1> 
  4059 00001DB6 BA[E91D0000]        <1> 	mov	edx, NEC_ERR		; LOAD RETURN ADDRESS
  4060 00001DBB 52                  <1> 	push	edx ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4061 00001DBC 88AF[C9610000]      <1> 	mov	[DSK_TRK+edi], ch	; SAVE NEW CYLINDER AS PRESENT POSITION
  4062 00001DC2 B40F                <1> 	mov	ah, 0Fh			; SEEK COMMAND TO NEC
  4063 00001DC4 E869FFFFFF          <1> 	call	NEC_OUTPUT
  4064 00001DC9 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4065 00001DCB 88DC                <1> 	mov	ah, bl			; OUTPUT DRIVE NUMBER
  4066 00001DCD E860FFFFFF          <1> 	call	NEC_OUTPUT
  4067 00001DD2 8AA7[C9610000]      <1> 	mov	ah, [DSK_TRK+edi]	; GET CYLINDER NUMBER
  4068 00001DD8 E855FFFFFF          <1> 	call	NEC_OUTPUT
  4069 00001DDD E827000000          <1> 	call	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4070                              <1> 
  4071                              <1> ;-----	WAIT FOR HEAD SETTLE
  4072                              <1> 
  4073                              <1> DO_WAIT:
  4074 00001DE2 9C                  <1> 	pushfd	; 24/12/2021		; SAVE STATUS
  4075 00001DE3 E818FFFFFF          <1> 	call	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4076 00001DE8 9D                  <1> 	popfd	; 24/12/2021		; RESTORE STATUS
  4077                              <1> RB:
  4078                              <1> NEC_ERR:
  4079                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4080                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4081 00001DE9 C3                  <1> 	retn				; RETURN TO CALLER
  4082                              <1> 
  4083                              <1> ;-------------------------------------------------------------------------------
  4084                              <1> ; RECAL
  4085                              <1> ;	RECALIBRATE DRIVE
  4086                              <1> ;
  4087                              <1> ; ON ENTRY:	EDI = DRIVE #
  4088                              <1> ;
  4089                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4090                              <1> ;-------------------------------------------------------------------------------
  4091                              <1> RECAL:
  4092                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4093                              <1> 	;push	cx
  4094                              <1> 	; 24/12/2021
  4095 00001DEA 51                  <1> 	push	ecx
  4096 00001DEB B8[071E0000]        <1> 	mov	eax, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4097 00001DF0 50                  <1> 	push	eax
  4098 00001DF1 B407                <1> 	mov	ah, 07h			; RECALIBRATE COMMAND
  4099 00001DF3 E83AFFFFFF          <1> 	call	NEC_OUTPUT
  4100 00001DF8 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4101 00001DFA 88DC                <1> 	mov	ah, bl
  4102 00001DFC E831FFFFFF          <1> 	call	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4103 00001E01 E803000000          <1> 	call	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4104 00001E06 58                  <1> 	pop	eax			; THROW AWAY ERROR
  4105                              <1> RC_BACK:
  4106                              <1> 	;pop	cx
  4107                              <1> 	; 24/12/2021
  4108 00001E07 59                  <1> 	pop	ecx
  4109 00001E08 C3                  <1> 	RETn
  4110                              <1> 
  4111                              <1> ;-------------------------------------------------------------------------------
  4112                              <1> ; CHK_STAT_2
  4113                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4114                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4115                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4116                              <1> ;
  4117                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4118                              <1> ;-------------------------------------------------------------------------------
  4119                              <1> CHK_STAT_2:
  4120                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4121 00001E09 B8[311E0000]        <1>         mov	eax, CS_BACK		; LOAD NEC_OUTPUT ERROR ADDRESS
  4122 00001E0E 50                  <1> 	push	eax
  4123 00001E0F E828000000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  4124 00001E14 721A                <1> 	jc	short J34		; IF ERROR, RETURN IT
  4125 00001E16 B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  4126 00001E18 E815FFFFFF          <1> 	call	NEC_OUTPUT
  4127 00001E1D E849000000          <1> 	call	RESULTS			; READ IN THE RESULTS
  4128 00001E22 720C                <1> 	jc	short J34
  4129 00001E24 A0[BD610000]        <1> 	mov	al, [NEC_STATUS]	; GET THE FIRST STATUS BYTE
  4130 00001E29 2460                <1> 	and	al, 01100000b		; ISOLATE THE BITS
  4131 00001E2B 3C60                <1> 	cmp	al, 01100000b		; TEST FOR CORRECT VALUE
  4132 00001E2D 7403                <1> 	jz	short J35		; IF ERROR, GO MARK IT
  4133 00001E2F F8                  <1> 	clc				; GOOD RETURN
  4134                              <1> J34:
  4135 00001E30 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  4136                              <1> CS_BACK:
  4137 00001E31 C3                  <1> 	retn
  4138                              <1> J35:
  4139 00001E32 800D[BC610000]40    <1> 	or	byte [DSKETTE_STATUS], BAD_SEEK
  4140 00001E39 F9                  <1> 	stc				; ERROR RETURN CODE
  4141 00001E3A EBF4                <1> 	jmp	short J34
  4142                              <1> 
  4143                              <1> ;-------------------------------------------------------------------------------
  4144                              <1> ; WAIT_INT
  4145                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4146                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4147                              <1> ;	IF THE DRIVE IS NOT READY.
  4148                              <1> ;
  4149                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4150                              <1> ;-------------------------------------------------------------------------------
  4151                              <1> 
  4152                              <1> ; 17/12/2014
  4153                              <1> ; 2.5 seconds waiting !
  4154                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4155                              <1> ; amount of time to wait for completion interrupt from NEC.
  4156                              <1> 
  4157                              <1> WAIT_INT:
  4158                              <1> 	; 12/07/2022
  4159                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4160 00001E3C FB                  <1> 	sti				; TURN ON INTERRUPTS, JUST IN CASE
  4161                              <1> 	; 12/07/2022
  4162                              <1> 	;clc				; CLEAR TIMEOUT INDICATOR
  4163                              <1>        ;mov	bl, 10			; CLEAR THE COUNTERS
  4164                              <1>        ;xor	cx, cx			; FOR 2 SECOND WAIT
  4165                              <1> 
  4166                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4167                              <1> 	;
  4168                              <1> 	;WAIT_FOR_MEM:	
  4169                              <1> 	;	Waits for a bit at a specified memory location pointed
  4170                              <1> 	;	to by ES:[DI] to become set.
  4171                              <1> 	;INPUT:
  4172                              <1> 	;	AH=Mask to test with.
  4173                              <1> 	;	ES:[DI] = memory location to watch.
  4174                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4175                              <1> 	;	     (normally 30 microseconds per period.)
  4176                              <1> 
  4177                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4178                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4179                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4180                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4181                              <1> 	; 27/02/2015
  4182 00001E3D B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4183                              <1> WFMS_CHECK_MEM:
  4184 00001E42 F605[B9610000]80    <1> 	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4185 00001E49 7516                <1>         jnz     short J37
  4186                              <1> WFMS_HI:
  4187 00001E4B E461                <1> 	in	al, PORT_B  ; 061h	; SYS1, wait for lo to hi
  4188 00001E4D A810                <1> 	test	al, 010h		; transition on memory
  4189 00001E4F 75FA                <1> 	jnz	short WFMS_HI		; refresh.
  4190                              <1> WFMS_LO:
  4191 00001E51 E461                <1> 	in	al, PORT_B		; SYS1
  4192 00001E53 A810                <1> 	test	al, 010h
  4193 00001E55 74FA                <1> 	jz	short WFMS_LO
  4194 00001E57 E2E9                <1>         loop	WFMS_CHECK_MEM
  4195                              <1> ;WFMS_OUTER_LP:
  4196                              <1> ;;	or	bl, bl			; check outer counter
  4197                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4198                              <1> ;	dec	bl
  4199                              <1> ;	jz	short J36A	
  4200                              <1> ;	jmp	short WFMS_CHECK_MEM
  4201                              <1> 
  4202                              <1> 	;17/12/2014
  4203                              <1> 	;16/12/2014
  4204                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4205                              <1> ;J36:
  4206                              <1> ;	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4207                              <1> ;	jnz	short J37
  4208                              <1> 	;16/12/2014
  4209                              <1> 	;loop	J36			; COUNT DOWN WHILE WAITING
  4210                              <1> 	;dec	bl			; SECOND LEVEL COUNTER
  4211                              <1> 	;jnz	short J36
  4212                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4213                              <1> ;	jb	short J36
  4214                              <1> 
  4215                              <1> ;WFMS_TIMEOUT:
  4216                              <1> ;J36A:
  4217 00001E59 800D[BC610000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4218 00001E60 F9                  <1> 	stc				; ERROR RETURN
  4219                              <1> J37:
  4220 00001E61 9C                  <1> 	pushf				; SAVE CURRENT CARRY
  4221 00001E62 8025[B9610000]7F    <1> 	and	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4222 00001E69 9D                  <1> 	popf				; RECOVER CARRY
  4223 00001E6A C3                  <1> 	retn				; GOOD RETURN CODE
  4224                              <1> 
  4225                              <1> ;-------------------------------------------------------------------------------
  4226                              <1> ; RESULTS
  4227                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4228                              <1> ;	FOLLOWING AN INTERRUPT.
  4229                              <1> ;
  4230                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4231                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4232                              <1> ;-------------------------------------------------------------------------------
  4233                              <1> RESULTS:
  4234                              <1> 	; 12/07/2022
  4235                              <1> 	; 11/07/2022
  4236                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4237 00001E6B 57                  <1> 	push	edi
  4238 00001E6C BF[BD610000]        <1> 	mov	edi, NEC_STATUS		; POINTER TO DATA AREA
  4239 00001E71 B307                <1> 	mov	bl, 7			; MAX STATUS BYTES
  4240 00001E73 66BAF403            <1> 	mov	dx, 03F4h		; STATUS PORT
  4241                              <1> 
  4242                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4243                              <1> 
  4244                              <1> _R10: 
  4245                              <1> 	; 16/12/2014
  4246                              <1> 	; wait for (max) 0.5 seconds
  4247                              <1> 	;mov	bh, 2			; HIGH ORDER COUNTER
  4248                              <1> 	;xor	cx, cx			; COUNTER
  4249                              <1> 
  4250                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4251                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4252                              <1> 	; 27/02/2015
  4253                              <1> 
  4254 00001E77 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4255                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4256                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4257                              <1> 
  4258                              <1> WFPSR_OUTER_LP:
  4259                              <1> 	;
  4260                              <1> WFPSR_CHECK_PORT:
  4261                              <1> J39:					; WAIT FOR MASTER
  4262 00001E7C EC                  <1> 	in	al, dx			; GET STATUS
  4263 00001E7D 24C0                <1> 	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4264 00001E7F 3CC0                <1> 	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4265 00001E81 7418                <1> 	jz	short J42		; STATUS AND DIRECTION OK
  4266                              <1> WFPSR_HI:
  4267 00001E83 E461                <1> 	in	al, PORT_B	;061h	; SYS1	; wait for hi to lo
  4268 00001E85 A810                <1> 	test	al, 010h		; transition on memory
  4269 00001E87 75FA                <1> 	jnz	short WFPSR_HI		; refresh.
  4270                              <1> WFPSR_LO:
  4271 00001E89 E461                <1> 	in	al, PORT_B		; SYS1
  4272 00001E8B A810                <1> 	test	al, 010h
  4273 00001E8D 74FA                <1> 	jz	short WFPSR_LO
  4274 00001E8F E2EB                <1>         loop	WFPSR_CHECK_PORT
  4275                              <1> 	
  4276                              <1> 	;; 27/02/2015
  4277                              <1> 	;;dec	bh
  4278                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4279                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4280                              <1> 
  4281                              <1> 	;;mov	byte [wait_count], 0
  4282                              <1> ;J39:					; WAIT FOR MASTER
  4283                              <1> ;	in	al, dx			; GET STATUS
  4284                              <1> ;	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4285                              <1> ;	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4286                              <1> ;	jz	short J42		; STATUS AND DIRECTION OK
  4287                              <1> 	;loop	J39			; LOOP TILL TIMEOUT
  4288                              <1> 	;dec	bh			; DECREMENT HIGH ORDER COUNTER
  4289                              <1> 	;jnz	short J39		; REPEAT TILL DELAY DONE
  4290                              <1> 	;
  4291                              <1> 	;;cmp	byte [wait_count], 10	; (10/18.2 seconds)
  4292                              <1> 	;;jb	short J39	
  4293                              <1> 
  4294                              <1> ;WFPSR_TIMEOUT:
  4295 00001E91 800D[BC610000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4296 00001E98 F9                  <1> 	stc				; SET ERROR RETURN
  4297 00001E99 EB26                <1> 	jmp	short POPRES		; POP REGISTERS AND RETURN
  4298                              <1> 
  4299                              <1> ;-----	READ IN THE STATUS
  4300                              <1> 
  4301                              <1> J42:
  4302 00001E9B EB00                <1> 	JMP	$+2			; I/O DELAY
  4303                              <1> 	;inc	dx			; POINT AT DATA PORT
  4304 00001E9D FEC2                <1> 	inc	dl
  4305 00001E9F EC                  <1> 	in	al, dx			; GET THE DATA
  4306                              <1> 	; 16/12/2014
  4307                              <1> 	NEWIODELAY
  2135 00001EA0 E6EB                <2>  out 0EBh,al
  4308                              <1> 	
  4309                              <1> 	;mov	[edi], al		; STORE THE BYTE
  4310                              <1> 	;inc	edi			; INCREMENT THE POINTER
  4311                              <1> 	; 11/07/2022
  4312 00001EA2 AA                  <1> 	stosb
  4313                              <1> 
  4314                              <1> 	; 16/12/2014
  4315                              <1> ;	push	cx
  4316                              <1> ;	mov	cx, 30
  4317                              <1> ;wdw2:
  4318                              <1> ;	NEWIODELAY
  4319                              <1> ;	loop	wdw2
  4320                              <1> ;	pop	cx
  4321                              <1> 
  4322                              <1> 	;mov	ecx,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4323                              <1> 	; 12/07/2022
  4324 00001EA3 29C9                <1> 	sub	ecx, ecx
  4325 00001EA5 B103                <1> 	mov	cl, 3
  4326 00001EA7 E800F5FFFF          <1> 	call	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4327                              <1> 	;dec	dx			; POINT AT STATUS PORT
  4328 00001EAC FECA                <1> 	dec	dl
  4329 00001EAE EC                  <1> 	in	al, dx			; GET STATUS
  4330                              <1> 	; 16/12/2014
  4331                              <1> 	NEWIODELAY
  2135 00001EAF E6EB                <2>  out 0EBh,al
  4332                              <1> 	;
  4333 00001EB1 A810                <1> 	test	al, 00010000b		; TEST FOR NEC STILL BUSY
  4334 00001EB3 740C                <1> 	jz	short POPRES		; RESULTS DONE ?
  4335                              <1> 
  4336 00001EB5 FECB                <1> 	dec	bl			; DECREMENT THE STATUS COUNTER
  4337 00001EB7 75BE                <1>         jnz	short _R10              ; GO BACK FOR MORE
  4338 00001EB9 800D[BC610000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES
  4339 00001EC0 F9                  <1> 	stc				; SET ERROR FLAG
  4340                              <1> 
  4341                              <1> ;-----	RESULT OPERATION IS DONE
  4342                              <1> POPRES:
  4343 00001EC1 5F                  <1> 	pop	edi
  4344 00001EC2 C3                  <1> 	retn				; RETURN WITH CARRY SET
  4345                              <1> 
  4346                              <1> ;-------------------------------------------------------------------------------
  4347                              <1> ; READ_DSKCHNG
  4348                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  4349                              <1> ;
  4350                              <1> ; ON ENTRY:	EDI = DRIVE #
  4351                              <1> ;
  4352                              <1> ; ON EXIT:	EDI = DRIVE #
  4353                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  4354                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  4355                              <1> ;		EAX, ECX, EDX DESTROYED
  4356                              <1> ;-------------------------------------------------------------------------------
  4357                              <1> READ_DSKCHNG:
  4358                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4359 00001EC3 E8B4FDFFFF          <1> 	call	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  4360 00001EC8 66BAF703            <1> 	mov	dx, 03F7h		; ADDRESS DIGITAL INPUT REGISTER
  4361 00001ECC EC                  <1> 	in	al, dx			; INPUT DIGITAL INPUT REGISTER
  4362 00001ECD A880                <1> 	test	al, DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  4363 00001ECF C3                  <1> 	retn				; RETURN TO CALLER WITH ZERO FLAG SET
  4364                              <1> 
  4365                              <1> fdc_int:  
  4366                              <1> 	  ; 30/07/2015	
  4367                              <1> 	  ; 16/02/2015
  4368                              <1> ;int_0Eh: ; 11/12/2014
  4369                              <1> 
  4370                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  4371                              <1> ; DISK_INT
  4372                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  4373                              <1> ;
  4374                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  4375                              <1> ;-------------------------------------------------------------------------------
  4376                              <1> DISK_INT_1:
  4377                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4378                              <1> 	;push	eax			; SAVE WORK REGISTER
  4379                              <1> 	; 24/12/2021
  4380 00001ED0 50                  <1> 	push	eax
  4381 00001ED1 1E                  <1> 	push	ds
  4382 00001ED2 66B81000            <1> 	mov	ax, KDATA
  4383 00001ED6 8ED8                <1> 	mov 	ds, ax
  4384 00001ED8 800D[B9610000]80    <1>         or	byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  4385 00001EDF B020                <1> 	mov	al, EOI			; END OF INTERRUPT MARKER
  4386 00001EE1 E620                <1> 	out	INTA00, al		; INTERRUPT CONTROL PORT
  4387 00001EE3 1F                  <1> 	pop	ds
  4388                              <1> 	;pop	ax			; RECOVER REGISTER
  4389                              <1> 	; 24/12/2021
  4390 00001EE4 58                  <1> 	pop	eax
  4391 00001EE5 CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  4392                              <1> 
  4393                              <1> ;-------------------------------------------------------------------------------
  4394                              <1> ; DSKETTE_SETUP
  4395                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  4396                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  4397                              <1> ;-------------------------------------------------------------------------------
  4398                              <1> DSKETTE_SETUP:
  4399                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4400                              <1> 	;push	eax			; SAVE REGISTERS
  4401                              <1> 	;push	ebx
  4402                              <1> 	;push	ecx
  4403 00001EE6 52                  <1> 	push	edx
  4404                              <1> 	;push	edi
  4405                              <1> 	; 14/12/2014
  4406                              <1> 	;mov	dword [DISK_POINTER], MD_TBL6
  4407                              <1> 	;
  4408                              <1> 	;or	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  4409                              <1> 
  4410 00001EE7 31FF                <1> 	xor	edi, edi 		; INITIALIZE DRIVE POINTER
  4411 00001EE9 29C9                <1> 	sub	ecx, ecx
  4412 00001EEB 66890D[C7610000]    <1> 	mov	[DSK_STATE], cx ; 0	; INITIALIZE STATES
  4413                              <1> 	; 08/07/2022
  4414                              <1> 	;and	byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  4415 00001EF2 800D[C4610000]C0    <1> 	or	byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  4416 00001EF9 880D[B9610000]      <1> 	mov	[SEEK_STATUS], cl ; 0	; INDICATE RECALIBRATE NEEDED
  4417 00001EFF 880D[BB610000]      <1> 	mov	[MOTOR_COUNT], cl ; 0	; INITIALIZE MOTOR COUNT
  4418 00001F05 880D[BA610000]      <1> 	mov	[MOTOR_STATUS], cl ; 0	; INITIALIZE DRIVES TO OFF STATE
  4419 00001F0B 880D[BC610000]      <1> 	mov	[DSKETTE_STATUS], cl ; 0 ; NO ERRORS
  4420                              <1> 	;
  4421                              <1> 	; 28/02/2015
  4422                              <1> 	;mov	word [cfd], 100h 
  4423 00001F11 E892F8FFFF          <1> 	call	DSK_RESET
  4424 00001F16 5A                  <1> 	pop	edx
  4425 00001F17 C3                  <1> 	retn
  4426                              <1> 
  4427                              <1> ;//////////////////////////////////////////////////////
  4428                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4429                              <1> ;
  4430                              <1> 
  4431                              <1> ; 12/07/2022
  4432                              <1> ;int13h: ; 21/02/2015
  4433                              <1> ;	pushfd
  4434                              <1> ;	push 	cs
  4435                              <1> ;	call 	DISK_IO
  4436                              <1> ;	retn
  4437                              <1> 
  4438                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  4439                              <1> ;/////////////////////////////////////////////////////////////////////
  4440                              <1> 
  4441                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4442                              <1> ; ((Direct call instead of int 13h simulation))
  4443                              <1> ;
  4444                              <1> ;		Function in AL
  4445                              <1> ;			0 = reset
  4446                              <1> ;			1 = read
  4447                              <1> ;			2 = write
  4448                              <1> ;		Disk drive number in DL
  4449                              <1> ;			0 & 1 = floppy disks	
  4450                              <1> ;			80h .. 83h = hard disks
  4451                              <1> ;		Sector address (LBA) in ECX
  4452                              <1> ;		Buffer address in EBX
  4453                              <1> ;		R/W sector count is (always) 1
  4454                              <1> ;
  4455                              <1> ;		Return:
  4456                              <1> ;			Status in AH (>0 = error code)
  4457                              <1> ;			if CF = 1 -> error code in AH
  4458                              <1> ;			if CF = 0 -> successful
  4459                              <1> ;			AL = undefined
  4460                              <1> ;
  4461                              <1> ;		Modified registers: (only) EAX
  4462                              <1> 
  4463                              <1> ; 10/07/2022
  4464                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4465                              <1> 
  4466                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  4467                              <1> ; 23/02/2015
  4468                              <1> ; 21/02/2015 (unix386.s)
  4469                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  4470                              <1> ;
  4471                              <1> ; Original Source Code:
  4472                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  4473                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  4474                              <1> ;
  4475                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  4476                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  4477                              <1> ;
  4478                              <1> 
  4479                              <1> ;The wait for controller to be not busy is 10 seconds.
  4480                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4481                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  4482                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  4483                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  4484                              <1> 
  4485                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  4486                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4487                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  4488                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  4489                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  4490                              <1> 
  4491                              <1> ;The wait for Data request on read and write longs is
  4492                              <1> ;2000 us. (?)
  4493                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  4494                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  4495                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  4496                              <1> 
  4497                              <1> ; Port 61h (PORT_B)
  4498                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  4499                              <1> 
  4500                              <1> ; 23/12/2014
  4501                              <1> %define CMD_BLOCK       ebp-8  ; 21/02/2015
  4502                              <1> 
  4503                              <1> 	; 11/07/2022
  4504                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4505                              <1> 
  4506                              <1> ;--- INT 13H -------------------------------------------------------------------
  4507                              <1> ;									       :
  4508                              <1> ; FIXED DISK I/O INTERFACE						       :
  4509                              <1> ;									       :
  4510                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  4511                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  4512                              <1> ;									       :
  4513                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  4514                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  4515                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  4516                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  4517                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  4518                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  4519                              <1> ;									       :
  4520                              <1> ;------------------------------------------------------------------------------:
  4521                              <1> ;									       :
  4522                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  4523                              <1> ;									       :
  4524                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  4525                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY                        :
  4526                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY                       :
  4527                              <1> ;									       :
  4528                              <1> ;------------------------------------------------------------------------------:
  4529                              <1> ;									       :
  4530                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  4531                              <1> ;									       :
  4532                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  4533                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  4534                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  4535                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  4536                              <1> ;									       :
  4537                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  4538                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  4539                              <1> ;				 (10 BITS TOTAL)			       :
  4540                              <1> ;									       :
  4541                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  4542                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  4543                              <1> ;									       :
  4544                              <1> ;		(EBX)   -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  4545                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  4546                              <1> ;									       :
  4547                              <1> ;------------------------------------------------------------------------------:
  4548                              <1> ; OUTPUT								       :
  4549                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  4550                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  4551                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  4552                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  4553                              <1> ;									       :
  4554                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  4555                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  4556                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  4557                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  4558                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  4559                              <1> ;		REWRITTEN.						       :
  4560                              <1> ;									       :
  4561                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  4562                              <1> ;	   INPUT:							       :
  4563                              <1> ;	     (DL) = DRIVE NUMBER					       :
  4564                              <1> ;	   OUTPUT:							       :
  4565                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  4566                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  4567                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  4568                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  4569                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  4570                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  4571                              <1> ;									       :
  4572                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  4573                              <1> ;	INFORMATION.							       :
  4574                              <1> ;									       :
  4575                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  4576                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  4577                              <1> ;									       :
  4578                              <1> ;-------------------------------------------------------------------------------
  4579                              <1> 
  4580                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  4581                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  4582                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  4583                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  4584                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  4585                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  4586                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  4587                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  4588                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  4589                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  4590                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  4591                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  4592                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  4593                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  4594                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  4595                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  4596                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  4597                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  4598                              <1> 
  4599                              <1> ;--------------------------------------------------------
  4600                              <1> ;							:
  4601                              <1> ; FIXED DISK PARAMETER TABLE				:
  4602                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  4603                              <1> ;							:
  4604                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  4605                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  4606                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  4607                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  4608                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  4609                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  4610                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  4611                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  4612                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  4613                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  4614                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  4615                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  4616                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  4617                              <1> ;							:
  4618                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  4619                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  4620                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  4621                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  4622                              <1> ;							:
  4623                              <1> ;--------------------------------------------------------
  4624                              <1> 
  4625                              <1> ;--------------------------------------------------------
  4626                              <1> ;							:
  4627                              <1> ; HARDWARE SPECIFIC VALUES				:
  4628                              <1> ;							:
  4629                              <1> ;  -  CONTROLLER I/O PORT				:
  4630                              <1> ;							:
  4631                              <1> ;     > WHEN READ FROM: 				:
  4632                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  4633                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  4634                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  4635                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  4636                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  4637                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  4638                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  4639                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  4640                              <1> ;							:
  4641                              <1> ;     > WHEN WRITTEN TO:				:
  4642                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  4643                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  4644                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  4645                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  4646                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  4647                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  4648                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  4649                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  4650                              <1> ;							:
  4651                              <1> ;--------------------------------------------------------
  4652                              <1> 
  4653                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  4654                              <1> ;HF1_PORT	equ	0170h	
  4655                              <1> ;HF_REG_PORT	EQU	03F6H
  4656                              <1> ;HF1_REG_PORT	equ	0376h
  4657                              <1> 
  4658                              <1> HDC1_BASEPORT	equ	1F0h
  4659                              <1> HDC2_BASEPORT	equ	170h		
  4660                              <1> 
  4661                              <1> align 2
  4662                              <1> 
  4663                              <1> ;-----		STATUS REGISTER
  4664                              <1> 
  4665                              <1> ST_ERROR	EQU	00000001B	;
  4666                              <1> ST_INDEX	EQU	00000010B	;
  4667                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  4668                              <1> ST_DRQ		EQU	00001000B	;
  4669                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  4670                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  4671                              <1> ST_READY	EQU	01000000B	;
  4672                              <1> ST_BUSY 	EQU	10000000B	;
  4673                              <1> 
  4674                              <1> ;-----		ERROR REGISTER
  4675                              <1> 
  4676                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  4677                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  4678                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  4679                              <1> ;		EQU	00001000B	; NOT USED
  4680                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  4681                              <1> ;		EQU	00100000B	; NOT USED
  4682                              <1> ERR_DATA_ECC	EQU	01000000B
  4683                              <1> ERR_BAD_BLOCK	EQU	10000000B
  4684                              <1> 
  4685                              <1> 
  4686                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  4687                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  4688                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  4689                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  4690                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  4691                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  4692                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  4693                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  4694                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  4695                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  4696                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  4697                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  4698                              <1> 
  4699                              <1> ;MAX_FILE	EQU	2
  4700                              <1> ;S_MAX_FILE	EQU	2
  4701                              <1> MAX_FILE	equ	4		; 22/12/2014
  4702                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  4703                              <1> 
  4704                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  4705                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  4706                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  4707                              <1> 
  4708                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  4709                              <1> 
  4710                              <1> ;-----		COMMAND BLOCK REFERENCE
  4711                              <1> 
  4712                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  4713                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  4714                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  4715                              <1> ; 19/12/2014
  4716                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  4717                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  4718                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4719                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4720                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  4721                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  4722                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  4723                              <1> 
  4724                              <1> align 2
  4725                              <1> 
  4726                              <1> ;----------------------------------------------------------------
  4727                              <1> ; FIXED DISK I/O SETUP						:
  4728                              <1> ;								:
  4729                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  4730                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  4731                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  4732                              <1> ;								:
  4733                              <1> ;----------------------------------------------------------------
  4734                              <1> 
  4735                              <1> 	; 12/07/2022
  4736                              <1> 	; 11/07/2022
  4737                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4738                              <1> 
  4739                              <1> DISK_SETUP:
  4740                              <1> 	;cli
  4741                              <1> 	;;mov	ax, ABS0 			; GET ABSOLUTE SEGMENT
  4742                              <1> 	;xor	ax, ax
  4743                              <1> 	;mov	ds, ax				; SET SEGMENT REGISTER
  4744                              <1> 	;mov	ax, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  4745                              <1> 	;mov	[DISK_VECTOR], ax		; INTO INT 40H
  4746                              <1> 	;mov	ax, [ORG_VECTOR+2]
  4747                              <1> 	;mov	[DISK_VECTOR+2], ax
  4748                              <1> 	;mov	word [ORG_VECTOR], DISK_IO	; FIXED DISK HANDLER
  4749                              <1> 	;mov	[ORG_VECTOR+2], cs
  4750                              <1> 	; 1st controller (primary master, slave) - IRQ 14
  4751                              <1> 	;;mov	word [HDISK_INT], HD_INT	; FIXED DISK INTERRUPT
  4752                              <1> 	;mov	word [HDISK_INT1], HD_INT	;
  4753                              <1> 	;;mov	[HDISK_INT+2], cs
  4754                              <1> 	;mov	[HDISK_INT1+2], cs
  4755                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  4756                              <1> 	;mov	word [HDISK_INT2], HD1_INT	;
  4757                              <1> 	;mov	[HDISK_INT2+2], cs
  4758                              <1> 	;
  4759                              <1> 	;;mov	word [HF_TBL_VEC], HD0_DPT	; PARM TABLE DRIVE 80
  4760                              <1> 	;;mov	word [HF_TBL_VEC+2], DPT_SEGM
  4761                              <1> 	;;mov	word [HF1_TBL_VEC], HD1_DPT	; PARM TABLE DRIVE 81
  4762                              <1> 	;;mov	word [HF1_TBL_VEC+2], DPT_SEGM
  4763                              <1> 	;push	cs
  4764                              <1> 	;pop	ds
  4765                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  4766                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  4767 00001F18 C705[D0610000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  4767 00001F20 0900                <1>
  4768                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  4769                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  4770 00001F22 C705[D4610000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  4770 00001F2A 0900                <1>
  4771                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  4772                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  4773 00001F2C C705[D8610000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  4773 00001F34 0900                <1>
  4774                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  4775                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  4776 00001F36 C705[DC610000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  4776 00001F3E 0900                <1>
  4777                              <1> 	;
  4778                              <1> 	;;in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  4779                              <1> 	;;;and	al, 0BFh
  4780                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  4781                              <1> 	;;;JMP	$+2
  4782                              <1> 	;;IODELAY
  4783                              <1> 	;;out	INTB01, al
  4784                              <1> 	;;IODELAY
  4785                              <1> 	;;in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  4786                              <1> 	;;and	al, 0FBh 		; SECOND CHIP
  4787                              <1> 	;;;JMP	$+2
  4788                              <1> 	;;IODELAY
  4789                              <1> 	;;out	INTA01, al
  4790                              <1> 	;
  4791                              <1> 	;sti
  4792                              <1> 	;;push	ds			; MOVE ABS0 POINTER TO
  4793                              <1> 	;;pop	es			; EXTRA SEGMENT POINTER
  4794                              <1> 	;;;call	DDS			; ESTABLISH DATA SEGMENT
  4795                              <1> 	;;mov	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  4796                              <1> 	;;mov	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  4797                              <1> 	;;mov	byte [CONTROL_BYTE],0
  4798                              <1> 	;;mov	byte [PORT_OFF],0	; ZERO CARD OFFSET
  4799                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  4800                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  4801                              <1> 	;mov	si, hd0_type
  4802 00001F40 BE[5E5C0000]        <1> 	mov	esi, hd0_type
  4803                              <1> 	;;mov	cx, 4
  4804                              <1> 	;mov	ecx, 4
  4805                              <1> 	; 11/07/2022
  4806 00001F45 29C9                <1> 	sub	ecx, ecx
  4807 00001F47 B104                <1> 	mov	cl, 4
  4808                              <1> hde_l:
  4809 00001F49 AC                  <1> 	lodsb
  4810 00001F4A 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  4811 00001F4C 7206                <1> 	jb	short _L4
  4812 00001F4E FE05[CC610000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  4813                              <1> _L4: ; 26/02/2015
  4814 00001F54 E2F3                <1> 	loop	hde_l	
  4815                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  4816                              <1> ;L4:
  4817                              <1> 	; 
  4818                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  4819                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  4820                              <1> 	;;mov 	cl, 3
  4821                              <1> 	;;
  4822                              <1> 	;;mov	dl, 80h			; CHECK THE CONTROLLER
  4823                              <1> ;;hdc_dl:
  4824                              <1> 	;;mov	ah, 14h			; USE CONTROLLER DIAGNOSTIC COMMAND
  4825                              <1> 	;;int	13h			; CALL BIOS WITH DIAGNOSTIC COMMAND
  4826                              <1> 	;;;jc	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  4827                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  4828                              <1> 	;;jnc	short hdc_reset0
  4829                              <1> 	;;loop	hdc_dl
  4830                              <1> 	;;; 27/12/2014
  4831                              <1> 	;;stc
  4832                              <1> 	;;retn
  4833                              <1> 	;
  4834                              <1> ;;hdc_reset0:
  4835                              <1> 	; 18/01/2015
  4836 00001F56 8A0D[CC610000]      <1> 	mov	cl, [HF_NUM]
  4837 00001F5C 20C9                <1> 	and	cl, cl
  4838 00001F5E 740D                <1> 	jz	short POD_DONE
  4839                              <1> 	;
  4840 00001F60 B27F                <1> 	mov	dl, 7Fh
  4841                              <1> hdc_reset1:
  4842 00001F62 FEC2                <1> 	inc	dl
  4843                              <1> 	;; 31/12/2015
  4844                              <1> 	;;push	dx
  4845                              <1> 	;;push	cx
  4846                              <1> 	;;push	ds
  4847                              <1> 	;;sub	ax, ax
  4848                              <1> 	;;mov	ds, ax
  4849                              <1> 	;;mov	ax, [TIMER_LOW]		; GET START TIMER COUNTS
  4850                              <1> 	;;pop	ds
  4851                              <1> 	;;mov	bx, ax
  4852                              <1> 	;;add	ax, 6*182		; 60 SECONDS* 18.2
  4853                              <1> 	;;mov	cx, ax
  4854                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  4855                              <1> 	;;
  4856                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  4857                              <1> 	;;call	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  4858                              <1> 	;;pop	cx
  4859                              <1> 	;;pop	dx
  4860                              <1> 	;;
  4861                              <1> 	; 18/01/2015
  4862                              <1> 	;mov	ah, 0Dh ; ALTERNATE RESET
  4863                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4864                              <1> 	;mov	ah, 5 ; ALTERNATE RESET
  4865                              <1> 	;;int	13h
  4866                              <1> 	;call	int13h
  4867                              <1> 	; 12/07/2022
  4868 00001F64 30C0                <1> 	xor	al, al  ; reset
  4869 00001F66 E803000000          <1> 	call	DISK_IO	
  4870                              <1> 	;
  4871 00001F6B E2F5                <1> 	loop	hdc_reset1
  4872                              <1> POD_DONE:
  4873 00001F6D C3                  <1> 	retn
  4874                              <1> 
  4875                              <1> ;----------------------------------------
  4876                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  4877                              <1> ;----------------------------------------
  4878                              <1> 
  4879                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4880                              <1> ; ((Direct call instead of int 13h simulation))
  4881                              <1> ;
  4882                              <1> ;		Function in AL
  4883                              <1> ;			0 = reset
  4884                              <1> ;			1 = read
  4885                              <1> ;			2 = write
  4886                              <1> ;		Disk drive number in DL
  4887                              <1> ;			0 & 1 = floppy disks	
  4888                              <1> ;			80h .. 83h = hard disks
  4889                              <1> ;		Sector address (LBA) in ECX
  4890                              <1> ;		Buffer address in EBX
  4891                              <1> ;		R/W sector count is (always) 1
  4892                              <1> ;
  4893                              <1> ;		Return:
  4894                              <1> ;			Status in AH (>0 = error code)
  4895                              <1> ;			if CF = 1 -> error code in AH
  4896                              <1> ;			if CF = 0 -> successful
  4897                              <1> ;			AL = undefined
  4898                              <1> ;
  4899                              <1> ;		Modified registers: (only) EAX
  4900                              <1> 	
  4901                              <1> 
  4902                              <1> ; 11/07/2022
  4903                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4904                              <1> 
  4905                              <1> DISK_IO:
  4906                              <1> 	; 11/07/2022
  4907                              <1> 	; save registers
  4908 00001F6E 57                  <1> 	push	edi			; ANY
  4909 00001F6F 56                  <1> 	push	esi			; ANY
  4910 00001F70 53                  <1> 	push	ebx			; BUFFER ADDRESS
  4911 00001F71 51                  <1> 	push	ecx			; SECTOR ADDRESS (LBA)
  4912 00001F72 52                  <1> 	push	edx			; DRIVE NUMBER (DL)
  4913                              <1> 
  4914                              <1> 	;cmp	dl, 80h			; TEST FOR FIXED DISK DRIVE
  4915                              <1> 	;;jae	short A1		; YES, HANDLE HERE
  4916                              <1> 	;;;;int	40H			; DISKETTE HANDLER
  4917                              <1> 	;;;call	int40h
  4918                              <1> 	;;jb	DISKETTE_IO_1
  4919                              <1> 	;; 24/12/2021
  4920                              <1> 	;jnb	short A1
  4921                              <1> 	;jmp	DISKETTE_IO_1
  4922                              <1> 
  4923                              <1> 	; 11/07/2022
  4924 00001F73 80FA80              <1> 	cmp	dl, 80h
  4925 00001F76 730B                <1> 	jae	short A1
  4926                              <1> 
  4927 00001F78 E8C8F6FFFF          <1> 	call	DISKETTE_IO_1
  4928                              <1> 
  4929                              <1> DISK_IO_RTN:
  4930                              <1> 	; restore registers
  4931 00001F7D 5A                  <1> 	pop	edx
  4932 00001F7E 59                  <1> 	pop	ecx
  4933 00001F7F 5B                  <1> 	pop	ebx
  4934 00001F80 5E                  <1> 	pop	esi
  4935 00001F81 5F                  <1> 	pop	edi
  4936 00001F82 C3                  <1> 	retn	
  4937                              <1> 
  4938                              <1> ;RET_2:
  4939                              <1> ;	retf	4			; BACK TO CALLER
  4940                              <1> 
  4941                              <1> A1:
  4942                              <1> 	; 11/07/2022
  4943                              <1> 	;sti				; ENABLE INTERRUPTS
  4944                              <1> 	;cmp	dl, (80h + S_MAX_FILE - 1)
  4945                              <1> 	;ja	short RET_2
  4946                              <1> 	
  4947                              <1> 	; 18/01/2015
  4948                              <1> 	;;or	ah, ah
  4949                              <1> 	;or	al, al ; 11/07/2022 (reset function)
  4950                              <1> 	;jz	short A3 ; 08/07/2022
  4951                              <1> 	
  4952                              <1> 	;;cmp	ah, 5  ; Alternate reset
  4953                              <1> 	;cmp	al, 5  ; 11/07/2022
  4954                              <1> 	;je	short A2
  4955                              <1> 	
  4956                              <1> 	; 11/07/2022 - no need to check
  4957                              <1> 	;		 (only kernel calls diskio functions)
  4958                              <1> 	;;cmp	ah, M1L/4 ; cmp ah, 6
  4959                              <1> 	;jb	short A3
  4960                              <1> 	;; BAD COMMAND
  4961                              <1>         ;mov     byte [DISK_STATUS1], BAD_CMD
  4962                              <1> ;RET_2:
  4963                              <1> 	;retf	4
  4964                              <1> 
  4965                              <1> 	; 11/07/2022
  4966                              <1> 	;stc
  4967                              <1> 	;retn
  4968                              <1> A2:
  4969                              <1> 	;sub	ah, ah	; Reset
  4970                              <1> 	; 11/07/2022
  4971                              <1> 	;sub	al, al
  4972                              <1> A3:
  4973                              <1> 					; SAVE REGISTERS DURING OPERATION
  4974 00001F83 C8080000            <1> 	enter	8,0			; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK
  4975                              <1> 	
  4976                              <1> 	; 11/07/2022
  4977                              <1> 	; 08/07/2022
  4978                              <1> 	;push	ebx			;  IN THE STACK, THE COMMAND BLOCK IS:
  4979                              <1> 	;push	ecx			;   @CMD_BLOCK == BYTE PTR [EBP]-8
  4980                              <1> 	;push	edx
  4981                              <1> 	;push	esi
  4982                              <1> 	;push	edi
  4983                              <1> 	
  4984 00001F87 E80D000000          <1> 	call	DISK_IO_CONT		; PERFORM THE OPERATION
  4985                              <1> 
  4986 00001F8C C9                  <1> 	leave	; 11/07/2022
  4987                              <1> 	
  4988 00001F8D 8A25[CB610000]      <1> 	mov	ah, [DISK_STATUS1]	; GET STATUS FROM OPERATION
  4989 00001F93 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  4990 00001F96 F5                  <1> 	cmc				; SUCCESS OR FAILURE
  4991                              <1> 	
  4992                              <1> 	;pop	edi			; RESTORE REGISTERS
  4993                              <1> 	;pop	esi
  4994                              <1>       	;pop	edx
  4995                              <1> 	;pop	ecx
  4996                              <1> 	;pop	ebx
  4997                              <1> 	
  4998                              <1> 	;leave				; ADJUST (ESP) AND RESTORE (EBP)
  4999                              <1> 	
  5000                              <1> 	; 11/07/2022
  5001                              <1> 	;retf	4			; THROW AWAY SAVED FLAGS
  5002                              <1> 
  5003 00001F97 EBE4                <1> 	jmp	short DISK_IO_RTN
  5004                              <1> 
  5005                              <1> DISK_IO_CONT:
  5006                              <1> 	; 17/07/2022
  5007                              <1> 	; 11/07/2022
  5008                              <1> 	;	INPUT:
  5009                              <1> 	;	    AL = 0 : reset
  5010                              <1> 	;	    AL = 1 : read
  5011                              <1> 	;	    Al = 2 : write
  5012                              <1> 	; 	
  5013                              <1> 	; 10/07/2022
  5014                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5015                              <1> SU0:
  5016 00001F99 C605[CB610000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; RESET THE STATUS INDICATOR
  5017                              <1> 	; 10/07/2022
  5018 00001FA0 89DE                <1> 	mov	esi, ebx ; 21/02/2015	; DATA (BUFFER) ADDRESS
  5019                              <1> 
  5020 00001FA2 8A1D[CC610000]      <1> 	mov	bl, [HF_NUM]		; GET NUMBER OF DRIVES
  5021 00001FA8 80E27F              <1> 	and	dl, 7Fh			; GET DRIVE AS 0 OR 1
  5022                              <1> 					; (get drive number as 0 to 3)
  5023 00001FAB 38D3                <1> 	cmp	bl, dl
  5024                              <1>         ;;jbe	BAD_COMMAND_POP         ; INVALID DRIVE
  5025                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5026                              <1> 	; 24/12/2021
  5027 00001FAD 7705                <1> 	ja	short su0_su1
  5028 00001FAF E98D000000          <1> 	jmp	BAD_COMMAND
  5029                              <1> su0_su1:
  5030                              <1>         ;;03/01/2015
  5031 00001FB4 29DB                <1> 	sub	ebx, ebx
  5032 00001FB6 88D3                <1> 	mov	bl, dl
  5033 00001FB8 883D[E0610000]      <1> 	mov	[LBAMode], bh  ; 0
  5034                              <1> 	;test	byte [ebx+hd0_type], 1	; LBA ready ?
  5035                              <1> 	;jz	short su1		; no
  5036                              <1> 	;inc	byte [LBAMode]
  5037                              <1> ;su1:
  5038                              <1> 	; 21/02/2015 (32 bit modification)
  5039                              <1> 	; 04/01/2015
  5040                              <1> 	;push	ax ; ***
  5041                              <1> 	; 24/12/2021
  5042 00001FBE 50                  <1> 	push	eax ; *** ; function (in AL) ; 11/07/2022
  5043                              <1> 	; 24/12/2021
  5044 00001FBF 52                  <1> 	push	edx ; *
  5045 00001FC0 50                  <1> 	push	eax ; function (in AL)	; 11/07/2022
  5046 00001FC1 E8C4030000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5047                              <1> 	; 02/02/2015
  5048 00001FC6 668B4310            <1> 	mov	ax, [ebx+16]   ; I/O port base address (1F0h, 170h)
  5049 00001FCA 66A3[525C0000]      <1> 	mov	[HF_PORT], ax
  5050 00001FD0 668B5312            <1> 	mov	dx, [ebx+18]   ; control port address (3F6h, 376h)
  5051 00001FD4 668915[545C0000]    <1> 	mov	[HF_REG_PORT], dx
  5052 00001FDB 8A4314              <1> 	mov	al, [ebx+20]   ; head register upper nibble (A0h,B0h,E0h,F0h)
  5053                              <1> 	; 23/02/2015
  5054 00001FDE A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5055 00001FE0 7406                <1> 	jz 	short su1
  5056 00001FE2 FE05[E0610000]      <1> 	inc	byte [LBAMode] ; 1 
  5057                              <1> su1: 	 
  5058 00001FE8 C0E804              <1> 	shr 	al, 4
  5059 00001FEB 2401                <1> 	and	al, 1			
  5060 00001FED A2[565C0000]        <1> 	mov	[hf_m_s], al 
  5061                              <1> 	;
  5062                              <1> 	; 03/01/2015
  5063 00001FF2 8A4308              <1> 	mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5064                              <1> 	;mov	dx, [HF_REG_PORT]	; Device Control register	
  5065 00001FF5 EE                  <1> 	out	dx, al			; SET EXTRA HEAD OPTION
  5066                              <1> 					; Control Byte: (= 08h, here)
  5067                              <1> 					; bit 0 - 0
  5068                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5069                              <1> 					; bit 2 - SRST (software RESET)
  5070                              <1> 					; bit 3 - use extra heads (8 to 15)
  5071                              <1> 					;         -always set to 1-	
  5072                              <1> 					; (bits 3 to 7 are reserved
  5073                              <1> 					;          for ATA devices)
  5074 00001FF6 8A25[CD610000]      <1> 	mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5075 00001FFC 80E4C0              <1> 	and	ah, 0C0h 		; CONTROL BYTE
  5076 00001FFF 08C4                <1> 	or	ah, al
  5077 00002001 8825[CD610000]      <1> 	mov	[CONTROL_BYTE], ah	
  5078                              <1> 	; 04/01/2015
  5079                              <1> 	;pop	ax
  5080                              <1> 	; 24/12/2021
  5081 00002007 58                  <1> 	pop	eax ; function (in AL) ; 11/07/2022
  5082                              <1> 	;pop	dx ; * ;; 14/02/2015
  5083                              <1> 	; 24/12/2021
  5084 00002008 5A                  <1> 	pop	edx ; *
  5085                              <1> 	;and	ah, ah	; Reset function ?
  5086 00002009 20C0                <1> 	and	al, al	; 11/07/2022
  5087 0000200B 7506                <1> 	jnz	short su2
  5088                              <1> 	;pop	ax ; ***
  5089                              <1> 	; 24/12/2021
  5090 0000200D 58                  <1> 	pop	eax ; *** 	
  5091                              <1> 	;;pop	bx
  5092 0000200E E9E4000000          <1>         jmp     DISK_RESET
  5093                              <1> su2:
  5094                              <1> 	; 11/07/2022
  5095                              <1> 	; ecx = sector address (lba)
  5096                              <1> 	;  dl = hard disk drive number (80h, 81h .. 83h)	 
  5097                              <1> 	;  al = function (0 = read, 1 = write)	
  5098                              <1> 
  5099 00002013 803D[E0610000]00    <1> 	cmp	byte [LBAMode], 0
  5100 0000201A 7620                <1> 	jna	short su3 ; convert LBA address to CHS parameters
  5101                              <1> 	
  5102                              <1> ;	; 02/02/2015 (LBA read/write function calls)
  5103                              <1> ;	;cmp	ah, 1Bh
  5104                              <1> ;	cmp	ah, 3 ; 08/07/2022
  5105                              <1> ;	jb	short lbarw1
  5106                              <1> ;	;;cmp	ah, 1Ch
  5107                              <1> ;	;cmp	ah, 4 ; 08/07/2022 
  5108                              <1> ;	;ja 	short invldfnc
  5109                              <1> ;	;;pop	dx ; * ; 14/02/2015
  5110                              <1> ;	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  5111                              <1> 
  5112 0000201C 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  5113                              <1> 
  5114                              <1> 	; 11/07/2022
  5115                              <1> 	;; 14/02/2015
  5116                              <1> 	;mov	cl, dl ; 14/02/2015
  5117                              <1> 
  5118                              <1> 	;;mov	dx, bx
  5119                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  5120                              <1> 	;;mov	bx, di
  5121                              <1> 	;mov	si, di ; Buffer offset
  5122                              <1> 
  5123                              <1> 	; 11/07/2022
  5124                              <1> 	;jmp	short lbarw2
  5125                              <1> 
  5126                              <1> ;lbarw1:
  5127                              <1> ;	; convert CHS to LBA
  5128                              <1> ;	;
  5129                              <1> ;	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  5130                              <1> ;	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  5131                              <1> ;	;	+ Sector - 1
  5132                              <1> ;	;push	dx ; * ;; 14/02/2015
  5133                              <1> ;	; 24/12/2021
  5134                              <1> ;	push	edx ; *
  5135                              <1> ;	;xor	dh, dh
  5136                              <1> ;	xor	edx, edx
  5137                              <1> ;	mov	dl, [ebx+14]	; sectors per track (logical)
  5138                              <1> ;	;xor	ah, ah
  5139                              <1> ;	xor	eax, eax
  5140                              <1> ;	mov	al, [ebx+2]	; heads (logical) 
  5141                              <1> ;	dec	al
  5142                              <1> ;	;inc	ax		; 0 =  256
  5143                              <1> ;	inc	eax ; 24/12/2021
  5144                              <1> ;	mul 	dx
  5145                              <1> ;		; AX = # of Heads * Sectors/Track
  5146                              <1> ;	mov	dx, cx
  5147                              <1> ;	;and	cx, 3Fh	 ; sector (1 to 63)
  5148                              <1> ;	and	ecx, 3fh
  5149                              <1> ;	xchg	dl, dh
  5150                              <1> ;	shr	dh, 6
  5151                              <1> ;		; DX = cylinder (0 to 1023)
  5152                              <1> ;	;mul 	dx
  5153                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder
  5154                              <1> ;	mul	edx
  5155                              <1> ;	dec	cl  ; sector - 1
  5156                              <1> ;	;add	ax, cx
  5157                              <1> ;	;adc	dx, 0
  5158                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1
  5159                              <1> ;	add	eax, ecx
  5160                              <1> ;	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  5161                              <1> ;	; 24/12/2021
  5162                              <1> ;	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  5163                              <1> ;	;push	dx
  5164                              <1> ;	;push	ax
  5165                              <1> ;	push	eax
  5166                              <1> ;	mov	al, [ebx+14]  ; sectors per track (logical)	
  5167                              <1> ;	mul	ch
  5168                              <1> ;		; AX = Head * Sectors/Track
  5169                              <1> ;	cwd
  5170                              <1> ;	;pop	dx
  5171                              <1> ;	pop	edx
  5172                              <1> ;	;add	ax, dx
  5173                              <1> ;	;pop	dx
  5174                              <1> ;	;adc	dx, 0 ; add carry bit
  5175                              <1> ;	add	eax, edx
  5176                              <1> ;
  5177                              <1> ;lbarw2:
  5178                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5179                              <1> 	
  5180 0000201E 29D2                <1> 	sub	edx, edx ; 21/02/2015
  5181                              <1> 	
  5182                              <1> 	; 11/07/2022
  5183                              <1> 	;mov	dl, cl ; 21/02/2015
  5184                              <1>         
  5185 00002020 C645F800            <1> 	mov     byte [CMD_BLOCK], 0 ; Features Register
  5186                              <1> 				; NOTE: Features register (1F1h, 171h)
  5187                              <1> 				; is not used for ATA device R/W functions. 
  5188                              <1> 				; It is old/obsolete 'write precompensation'
  5189                              <1> 				; register and error register
  5190                              <1> 				; for old ATA/IDE devices.
  5191                              <1> 	; 18/01/2014
  5192                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  5193 00002024 8A0D[565C0000]      <1> 	mov	cl, [hf_m_s]
  5194                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  5195                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  5196                              <1> 				; bit 6 = 1 = LBA mode
  5197                              <1> 				; bit 7 = 1
  5198 0000202A 80C90E              <1> 	or	cl, 0Eh ; 1110b
  5199                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  5200 0000202D 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  5201 00002032 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  5202                              <1> 	;or	dh, ch
  5203 00002035 09C8                <1> 	or	eax, ecx	
  5204                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  5205                              <1> 				  ; (Sector Number Register)
  5206                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  5207                              <1> 				  ; (Cylinder Low Register)
  5208                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  5209                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  5210                              <1> 				  ; (Cylinder High Register)
  5211                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  5212                              <1> 				  ; (Drive/Head Register)
  5213                              <1> 	
  5214                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  5215 00002037 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  5216                              <1> 	;14/02/2015
  5217                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  5218 0000203A EB3D                <1> 	jmp	short su4
  5219                              <1> su3:
  5220                              <1> 	; 02/02/2015 
  5221                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  5222                              <1> 	;cmp 	ah, 14h
  5223                              <1> 	;jna 	short chsfnc
  5224                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5225                              <1> 	;cmp	ah, 2
  5226                              <1> 	;jna	short chsfnc
  5227                              <1> 	; 11/07/2022 
  5228                              <1> 	; (al = function, read = 1 or write = 2)
  5229 0000203C 3C02                <1> 	cmp	al, 2 
  5230 0000203E 760B                <1> 	jna	short chsfnc
  5231                              <1> invldfnc:
  5232                              <1>         ; 14/02/2015  
  5233                              <1> 	;pop	es ; **
  5234                              <1>         ;pop	ax ; ***
  5235                              <1>         ; 24/12/2021
  5236 00002040 58                  <1> 	pop	eax ; ***
  5237                              <1> 	;;jmp	short BAD_COMMAND_POP
  5238                              <1> 	; 11/07/2022
  5239                              <1>         ;jmp     short BAD_COMMAND
  5240                              <1> 
  5241                              <1> 	; 11/07/2022
  5242                              <1> BAD_COMMAND:
  5243 00002041 C605[CB610000]01    <1> 	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5244                              <1> 	;mov	al, 0
  5245 00002048 28C0                <1> 	sub	al, al ; 0
  5246 0000204A C3                  <1> 	retn
  5247                              <1> 
  5248                              <1> chsfnc:	
  5249 0000204B 668B4305            <1> 	mov	ax, [ebx+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  5250                              <1> 	;shr	ax, 2
  5251                              <1> 	; 17/07/2022
  5252 0000204F C1E802              <1> 	shr	eax, 2
  5253 00002052 8845F8              <1> 	mov	[CMD_BLOCK], al
  5254                              <1> 	;
  5255                              <1> 	;;mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5256                              <1> 	;;push	edx ; *
  5257                              <1> 	;;mov	dx, [HF_REG_PORT]
  5258                              <1> 	;;out	dx, al			; SET EXTRA HEAD OPTION
  5259                              <1> 	;;pop	edx ; * 
  5260                              <1> 	;;mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5261                              <1> 	;;and	ah, 0C0h 		; CONTROL BYTE	
  5262                              <1> 	;;or	ah, al
  5263                              <1> 	;;mov	[CONTROL_BYTE], ah
  5264                              <1> 	;
  5265 00002055 88C8                <1> 	mov	al, cl			; GET SECTOR NUMBER
  5266 00002057 243F                <1> 	and	al, 3Fh
  5267 00002059 8845FA              <1> 	mov	[CMD_BLOCK+2], al
  5268 0000205C 886DFB              <1> 	mov	[CMD_BLOCK+3], ch 	; GET CYLINDER NUMBER
  5269 0000205F 88C8                <1> 	mov	al, cl
  5270 00002061 C0E806              <1> 	shr	al, 6
  5271 00002064 8845FC              <1> 	mov	[CMD_BLOCK+4], al	; CYLINDER HIGH ORDER 2 BITS
  5272                              <1> 	;;05/01/2015
  5273                              <1> 	;;mov	al, dl			; DRIVE NUMBER
  5274 00002067 A0[565C0000]        <1> 	mov	al, [hf_m_s]
  5275 0000206C C0E004              <1> 	shl	al, 4
  5276 0000206F 80E60F              <1> 	and	dh, 0Fh			; HEAD NUMBER
  5277 00002072 08F0                <1> 	or	al, dh
  5278 00002074 0CA0                <1> 	or	al, 80h+20h		; ECC AND 512 BYTE SECTORS
  5279 00002076 8845FD              <1> 	mov	[CMD_BLOCK+5], al	; ECC/SIZE/DRIVE/HEAD
  5280                              <1> su4:
  5281                              <1> 	;; 14/02/2015
  5282                              <1>         ;;pop	ax
  5283                              <1>         ;;mov	[CMD_BLOCK+1], AL	; SECTOR COUNT
  5284                              <1>         ;;push	ax
  5285                              <1>         ;;mov	al, ah			; GET INTO LOW BYTE
  5286                              <1>         ;;xor	ah, ah			; ZERO HIGH BYTE
  5287                              <1>         ;;sal	ax, 1			; *2 FOR TABLE LOOKUP
  5288                              <1> 	;pop	ax ; ***
  5289                              <1> 	; 24/12/2021
  5290 00002079 58                  <1> 	pop	eax ; *** ; function (in AL) ; 11/07/2022
  5291                              <1> 	
  5292                              <1> 	;mov	[CMD_BLOCK+1], al
  5293 0000207A C645F901            <1>         mov	byte [CMD_BLOCK+1], 1 ; (always 1 sector r/w)
  5294                              <1> 
  5295                              <1> 	; 11/07/2022
  5296                              <1> 	;mov	ebx, esi
  5297                              <1> 	; (esi = buffer address)	
  5298                              <1> 
  5299 0000207E 3C02                <1> 	cmp	al, 2
  5300 00002080 742D                <1> 	je	short DISK_WRITE
  5301                              <1> 
  5302                              <1> 	;jmp	short DISK_READ
  5303                              <1> 
  5304                              <1> ;	;xor	ebx, ebx
  5305                              <1> ;	;mov	bl, ah
  5306                              <1> ;
  5307                              <1> ;       ;xor	bh, bh
  5308                              <1> ;       ;sal	bx, 1
  5309                              <1> ;       sal	bx, 2	; 32 bit offset (21/02/2015)
  5310                              <1> ;	;;mov	si, ax			; PUT INTO SI FOR BRANCH
  5311                              <1> ;       ;;cmp	ax, M1L			; TEST WITHIN RANGE
  5312                              <1> ;       ;;jnb	short BAD_COMMAND_POP
  5313                              <1> ;   	; 08/07/2022
  5314                              <1> ;	;cmp	ebx, M1L
  5315                              <1> ;	;jnb	short BAD_COMMAND
  5316                              <1> ;
  5317                              <1> ;	xchg	ebx, esi
  5318                              <1> ;
  5319                              <1> ;	;;;pop	ax			; RESTORE AX
  5320                              <1> ;	;;;pop	bx			; AND DATA ADDRESS
  5321                              <1> ;	
  5322                              <1> ;	;;push	cx
  5323                              <1> ;	;;push	ax			; ADJUST ES:BX
  5324                              <1> ;	;mov	cx, bx			; GET 3 HIGH ORDER NIBBLES OF BX
  5325                              <1> ;	;shr	cx, 4
  5326                              <1> ;	;mov	ax, es
  5327                              <1> ;	;add	ax, cx
  5328                              <1> ;	;mov	es, ax
  5329                              <1> ;	;and	bx, 000Fh		; ES:BX CHANGED TO ES:000X
  5330                              <1> ;	;;pop	ax
  5331                              <1> ;	;;pop	cx
  5332                              <1> ;
  5333                              <1> ;	jmp	dword [esi+M1]
  5334                              <1> 
  5335                              <1> ;;BAD_COMMAND_POP:
  5336                              <1> ;;	pop	ax
  5337                              <1> ;;	pop	bx
  5338                              <1> ;
  5339                              <1> ;	; 11/07/2022
  5340                              <1> ;BAD_COMMAND:
  5341                              <1> ;	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5342                              <1> ;	;mov	al, 0
  5343                              <1> ;	sub	al, al ; 0
  5344                              <1> ;	retn
  5345                              <1> 
  5346                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5347                              <1> 
  5348                              <1> ;----------------------------------------
  5349                              <1> ;	DISK READ ROUTINE    (AH = 01H) :
  5350                              <1> ;----------------------------------------
  5351                              <1> ; 
  5352                              <1> DISK_READ:
  5353 00002082 C645FE20            <1> 	mov	byte [CMD_BLOCK+6], READ_CMD
  5354                              <1>         ;jmp	COMMANDI
  5355                              <1> 
  5356                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5357                              <1> 
  5358                              <1> ;----------------------------------------
  5359                              <1> ; COMMANDI				:
  5360                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  5361                              <1> ;	NSECTOR RETURNS ZERO		:
  5362                              <1> ;----------------------------------------
  5363                              <1> COMMANDI:
  5364                              <1> 	; 11/07/2022 
  5365                              <1> 	;	(check 64K boundary is not needed)
  5366                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5367                              <1> 	;jc	short CMD_ABORT
  5368                              <1> 	
  5369                              <1> 	;mov	di, bx
  5370                              <1> 	; 11/07/2022
  5371                              <1> 	; (esi = buffer address)
  5372                              <1> 	;mov	edi, ebx ; 21/02/2015
  5373 00002086 89F7                <1> 	mov	edi, esi ; 11/07/2022	
  5374                              <1> 
  5375 00002088 E8A8010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5376 0000208D 751F                <1> 	jnz	short CMD_ABORT
  5377                              <1> CMD_I1:
  5378 0000208F E813020000          <1> 	call	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  5379 00002094 7518                <1> 	jnz	short TM_OUT		; TIME OUT
  5380                              <1> 	;;mov	cx,256			; SECTOR SIZE IN WORDS
  5381                              <1> 	;mov	ecx, 256 ; 21/02/2015	
  5382 00002096 29C9                <1> 	sub	ecx, ecx
  5383 00002098 FEC5                <1> 	inc	ch
  5384                              <1> 	; ecx = 256
  5385                              <1> 	;mov	dx, HF_PORT
  5386 0000209A 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]
  5387 000020A1 FA                  <1> 	cli
  5388 000020A2 FC                  <1> 	cld
  5389 000020A3 F3666D              <1> 	rep	insw			; GET THE SECTOR
  5390 000020A6 FB                  <1> 	sti
  5391                              <1> 	
  5392                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT
  5393                              <1> 	;jz	short CMD_I3
  5394                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5395                              <1> 	;jc	short TM_OUT
  5396                              <1> 	;;mov	dx, HF_PORT
  5397                              <1> 	;mov	dx,[HF_PORT]
  5398                              <1> 	;xor	ecx, ecx	
  5399                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5400                              <1> 	;mov	cl, 4
  5401                              <1> ;CMD_I2: 
  5402                              <1> 	;inc	al, dx
  5403                              <1> 	;mov 	[edi], al ; 21/02/2015
  5404                              <1> 	;inc	edi
  5405                              <1> 	;loop	CMD_I2
  5406                              <1> CMD_I3: 
  5407 000020A7 E817010000          <1> 	call	CHECK_STATUS
  5408 000020AC 7500                <1> 	jnz	short CMD_ABORT		; ERROR RETURNED
  5409                              <1> 	; 11/07/2022
  5410                              <1> 	; (sector count = 1)
  5411                              <1> 	;dec	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  5412                              <1> 	;jnz	SHORT CMD_I1
  5413                              <1> CMD_ABORT:
  5414                              <1> TM_OUT: 
  5415 000020AE C3                  <1> 	retn
  5416                              <1> 
  5417                              <1> ;---------------------------------------------------
  5418                              <1> 
  5419                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5420                              <1> 
  5421                              <1> ;----------------------------------------
  5422                              <1> ;	DISK WRITE ROUTINE   (AH = 02H) :
  5423                              <1> ;----------------------------------------
  5424                              <1> 
  5425                              <1> DISK_WRITE:
  5426 000020AF C645FE30            <1> 	mov	byte [CMD_BLOCK+6], WRITE_CMD
  5427                              <1>         ;JMP	COMMANDO
  5428                              <1> 
  5429                              <1> ; 16/07/2022
  5430                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5431                              <1> 
  5432                              <1> ;----------------------------------------
  5433                              <1> ; COMMANDO				:
  5434                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  5435                              <1> ;	NSECTOR RETURNS ZERO		:
  5436                              <1> ;----------------------------------------
  5437                              <1> COMMANDO:
  5438                              <1> 	; 11/07/2022 
  5439                              <1> 	;	(check 64K boundary is not needed)
  5440                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5441                              <1> 	;jc	short CMD_ABORT
  5442                              <1> CMD_OF:
  5443                              <1> 	; 11/07/2022
  5444                              <1> 	; (esi = ebx = buffer address)
  5445                              <1> 	;mov	esi, ebx ; 21/02/2015
  5446 000020B3 E87D010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5447 000020B8 75F4                <1> 	jnz	short CMD_ABORT
  5448 000020BA E83F020000          <1> 	call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5449 000020BF 72ED                <1> 	jc	short TM_OUT		; TOO LONG
  5450                              <1> CMD_O1:
  5451                              <1> 	; 16/07/2022
  5452 000020C1 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]
  5453                              <1> 
  5454                              <1> 	; 10/07/2022
  5455                              <1> 	;mov	ecx, 256 ; 21/02/2015
  5456 000020C8 31C9                <1> 	xor	ecx, ecx
  5457 000020CA FEC5                <1> 	inc	ch
  5458                              <1> 	; ecx = 256
  5459 000020CC FA                  <1> 	cli
  5460 000020CD FC                  <1> 	cld
  5461 000020CE F3666F              <1> 	rep	outsw
  5462 000020D1 FB                  <1> 	sti
  5463                              <1> 
  5464                              <1> 	; 10/07/2022
  5465                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT
  5466                              <1> 	;jz	short CMD_O3
  5467                              <1> 	;
  5468                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5469                              <1> 	;jc	short TM_OUT
  5470                              <1> 	;;mov	dx, HF_PORT
  5471                              <1> 	;mov	dx, [HF_PORT]
  5472                              <1> 	;sub	ecx, ecx	
  5473                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5474                              <1> 	;mov	cl, 4
  5475                              <1> ;CMD_O2:
  5476                              <1> 	;;lodsb
  5477                              <1> 	;mov	al, [esi]
  5478                              <1> 	;out	dx, al
  5479                              <1> 	;inc	esi
  5480                              <1> 	;loop	CMD_O2
  5481                              <1> 
  5482                              <1> CMD_O3:
  5483 000020D2 E8D0010000          <1> 	call	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  5484 000020D7 75D5                <1> 	jnz	short TM_OUT		; ERROR RETURNED
  5485 000020D9 E8E5000000          <1> 	call	CHECK_STATUS
  5486 000020DE 75CE                <1> 	jnz	short CMD_ABORT
  5487                              <1> 
  5488                              <1> 	; 11/07/2022
  5489                              <1> 	; (sector count = 1)
  5490                              <1> 	;test	byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE
  5491                              <1> 	;jnz	short CMD_O1
  5492                              <1> 	
  5493                              <1> 	;mov	dx, HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  5494 000020E0 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]
  5495 000020E7 80C202              <1> 	add	dl, 2
  5496                              <1> 	;inc	dl
  5497                              <1> 	;inc	dl
  5498 000020EA EC                  <1> 	in	al, dx			;
  5499 000020EB A8FF                <1> 	test	al, 0FFh 		;
  5500 000020ED 7407                <1> 	jz	short CMD_O4		; COUNT = 0  OK
  5501 000020EF C605[CB610000]BB    <1> 	mov	byte [DISK_STATUS1], UNDEF_ERR 
  5502                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  5503                              <1> CMD_O4:
  5504 000020F6 C3                  <1> 	retn
  5505                              <1> 
  5506                              <1> ; 10/07/2022
  5507                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5508                              <1> 
  5509                              <1> ;----------------------------------------
  5510                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  5511                              <1> ;----------------------------------------
  5512                              <1> 
  5513                              <1> ; 18-1-2015 : one controller reset (not other one)
  5514                              <1> 
  5515                              <1> DISK_RESET:
  5516 000020F7 FA                  <1> 	cli
  5517 000020F8 E4A1                <1> 	in	al, INTB01		; GET THE MASK REGISTER
  5518                              <1> 	;JMP	$+2
  5519                              <1> 	IODELAY
  2130 000020FA EB00                <2>  jmp short $+2
  2131 000020FC EB00                <2>  jmp short $+2
  5520                              <1> 	;and	al, 0BFh 		; ENABLE FIXED DISK INTERRUPT
  5521 000020FE 243F                <1> 	and	al, 3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  5522 00002100 E6A1                <1> 	out	INTB01, al
  5523 00002102 FB                  <1> 	sti				; START INTERRUPTS
  5524                              <1> 	; 14/02/2015
  5525                              <1> 	;mov	di, dx
  5526                              <1> 	; 24/12/2021
  5527 00002103 89D7                <1> 	mov	edi, edx	
  5528                              <1> 	; 04/01/2015
  5529                              <1> 	;xor	di,di
  5530                              <1> drst0:
  5531 00002105 B004                <1> 	mov	al, 04h  ; bit 2 - SRST 
  5532                              <1> 	;mov	dx, HF_REG_PORT
  5533 00002107 668B15[545C0000]    <1> 	mov	dx, [HF_REG_PORT]
  5534 0000210E EE                  <1> 	out	dx, al			; RESET
  5535                              <1> ;	mov	cx, 10			; DELAY COUNT
  5536                              <1> ;DRD:	dec	cx
  5537                              <1> ;	jnz	short DRD		; WAIT 4.8 MICRO-SEC
  5538                              <1> 	;mov	cx, 2			; wait for 30 micro seconds	
  5539                              <1>         ;mov	ecx, 2 ; 21/02/2015
  5540                              <1> 	; 10/07/2022
  5541 0000210F 29C9                <1> 	sub	ecx, ecx
  5542 00002111 B102                <1> 	mov	cl, 2
  5543 00002113 E894F2FFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  5544                              <1>                                         ; 40 micro seconds)
  5545 00002118 A0[CD610000]        <1> 	mov	al, [CONTROL_BYTE]
  5546 0000211D 240F                <1> 	and	al, 0Fh			; SET HEAD OPTION
  5547 0000211F EE                  <1> 	out	dx, al			; TURN RESET OFF
  5548 00002120 E8B2010000          <1> 	call	NOT_BUSY
  5549 00002125 7514                <1> 	jnz	short DRERR		; TIME OUT ON RESET
  5550 00002127 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]
  5551 0000212E FEC2                <1> 	inc	dl  ; HF_PORT+1
  5552                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  5553                              <1>         ;mov	cl, 10
  5554                              <1>         ;mov     ecx, 10 ; 21/02/2015
  5555                              <1> 	; 10/07/2022
  5556                              <1> 	;xor	ecx, ecx
  5557 00002130 B10A                <1> 	mov	cl, 10 
  5558                              <1> drst1:
  5559 00002132 EC                  <1> 	in	al, dx			; GET RESET STATUS
  5560 00002133 3C01                <1> 	cmp	al, 1
  5561                              <1> 	; 04/01/2015
  5562 00002135 740C                <1> 	jz	short drst2
  5563                              <1> 	;jnz	short DRERR		; BAD RESET STATUS
  5564                              <1>         	; Drive/Head Register - bit 4
  5565                              <1> 	;loop	drst1
  5566                              <1> 	; 10/07/2022
  5567 00002137 FEC9                <1> 	dec	cl
  5568 00002139 75F7                <1> 	jnz	short drst1
  5569                              <1> DRERR:	
  5570 0000213B C605[CB610000]05    <1> 	mov	byte [DISK_STATUS1], BAD_RESET ; CARD FAILED
  5571 00002142 C3                  <1> 	retn
  5572                              <1> drst2:
  5573                              <1> 	; 14/02/2015
  5574                              <1> 	;mov	dx, di
  5575                              <1> 	; 24/12/2021
  5576 00002143 89FA                <1> 	mov	edx, edi
  5577                              <1> ;drst3:
  5578                              <1> ;	; 05/01/2015
  5579                              <1> ;	shl 	di, 1
  5580                              <1> ;	; 04/01/2015
  5581                              <1> ;	mov	ax, [di+hd_cports]
  5582                              <1> ;	cmp	ax, [HF_REG_PORT]
  5583                              <1> ;	je	short drst4
  5584                              <1> ;	mov	[HF_REG_PORT], ax
  5585                              <1> ;	; 03/01/2015
  5586                              <1> ;	mov	ax, [di+hd_ports]
  5587                              <1> ;       mov     [HF_PORT], ax
  5588                              <1> ;	; 05/01/2014
  5589                              <1> ;	shr	di, 1
  5590                              <1> ;	; 04/01/2015
  5591                              <1> ;	jmp	short drst0	; reset other controller
  5592                              <1> ;drst4:
  5593                              <1> ;	; 05/01/2015
  5594                              <1> ;	shr	di, 1
  5595                              <1> ;	mov	al, [di+hd_dregs]
  5596                              <1> ;	and	al, 10h ; bit 4 only
  5597                              <1> ;	shr	al, 4 ; bit 4  -> bit 0
  5598                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  5599                              <1> 	;
  5600 00002145 A0[565C0000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  5601 0000214A A801                <1> 	test	al, 1
  5602                              <1> 	;jnz	short drst6
  5603 0000214C 7516                <1>         jnz     short drst4
  5604 0000214E 8065FDEF            <1> 	and	byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0
  5605                              <1> ;drst5:
  5606                              <1> drst3:
  5607 00002152 E813000000          <1> 	call	INIT_DRV		; SET MAX HEADS
  5608                              <1> 	;mov	dx, di
  5609 00002157 E8A3000000          <1> 	call	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  5610                              <1> 	; 04/01/2014
  5611                              <1> ;	inc	di
  5612                              <1> ;	mov	dx, di
  5613                              <1> ;	cmp	dl, [HF_NUM]
  5614                              <1> ;	jb	short drst3
  5615                              <1> ;DRE:
  5616 0000215C C605[CB610000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; IGNORE ANY SET UP ERRORS
  5617 00002163 C3                  <1> 	retn
  5618                              <1> ;drst6:
  5619                              <1> drst4:		; Drive/Head Register - bit 4
  5620 00002164 804DFD10            <1> 	or	byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1     
  5621                              <1>         ;jmp    short drst5
  5622 00002168 EBE8                <1>         jmp     short drst3
  5623                              <1> 
  5624                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5625                              <1> 
  5626                              <1> ;----------------------------------------
  5627                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  5628                              <1> ;----------------------------------------
  5629                              <1> 	; 03/01/2015
  5630                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  5631                              <1> 	; logical sector per logical track
  5632                              <1> 	; and logical heads - 1 would be set but
  5633                              <1> 	; it is seen as it will be good
  5634                              <1> 	; if physical parameters will be set here
  5635                              <1> 	; because, number of heads <= 16.
  5636                              <1> 	; (logical heads usually more than 16)
  5637                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  5638                              <1> 	;	== INT 13h physical parameters
  5639                              <1> 
  5640                              <1> ;INIT_DRV:
  5641                              <1> ;	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5642                              <1> ;	call	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  5643                              <1> ;	mov	al, [es:bx+2]		; GET NUMBER OF HEADS
  5644                              <1> ;	dec	al			; CONVERT TO 0-INDEX
  5645                              <1> ;	mov	ah, [CMD_BLOCK+5] 	; GET SDH REGISTER
  5646                              <1> ;	and	ah, 0F0h 		; CHANGE HEAD NUMBER
  5647                              <1> ;	or	ah, al			; TO MAX HEAD
  5648                              <1> ;	mov	[CMD_BLOCK+5], ah
  5649                              <1> ;	mov	al, [es:bx+14]		; MAX SECTOR NUMBER
  5650                              <1> ;	mov	[CMD_BLOCK+1], al
  5651                              <1> ;	sub	ax, ax
  5652                              <1> ;	mov	[CMD_BLOCK+3], al 	; ZERO FLAGS
  5653                              <1> ;	call	COMMAND 		; TELL CONTROLLER
  5654                              <1> ;	jnz	short INIT_EXIT		; CONTROLLER BUSY ERROR
  5655                              <1> ;	call	NOT_BUSY		; WAIT FOR IT TO BE DONE
  5656                              <1> ;	jnz	short INIT_EXIT		; TIME OUT
  5657                              <1> ;	call	CHECK_STATUS
  5658                              <1> ;INIT_EXIT:
  5659                              <1> ;	retn
  5660                              <1> 
  5661                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5662                              <1> 
  5663                              <1> ; 04/01/2015
  5664                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  5665                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  5666                              <1> INIT_DRV:
  5667                              <1> 	;xor	ah, ah
  5668 0000216A 31C0                <1> 	xor	eax, eax ; 21/02/2015
  5669 0000216C B00B                <1> 	mov	al, 11 ; Physical heads from translated HDPT
  5670 0000216E 3825[E0610000]      <1>         cmp     [LBAMode], ah   ; 0
  5671 00002174 7702                <1> 	ja	short idrv0
  5672 00002176 B002                <1> 	mov	al, 2  ; Physical heads from standard HDPT
  5673                              <1> idrv0:
  5674                              <1> 	; DL = drive number (0 based)
  5675 00002178 E80D020000          <1> 	call	GET_VEC
  5676                              <1> 	;push	bx
  5677 0000217D 53                  <1> 	push	ebx ; 21/02/2015
  5678                              <1> 	;add	bx, ax
  5679 0000217E 01C3                <1> 	add	ebx, eax
  5680                              <1> 	;; 05/01/2015
  5681 00002180 8A25[565C0000]      <1> 	mov	ah, [hf_m_s] ; drive number (0= master, 1= slave)
  5682                              <1> 	;;and 	ah, 1 
  5683 00002186 C0E404              <1> 	shl	ah, 4
  5684 00002189 80CCA0              <1> 	or	ah, 0A0h  ; Drive/Head register - 10100000b (A0h)	
  5685                              <1> 	;mov	al, [es:bx]
  5686 0000218C 8A03                <1> 	mov	al, [ebx] ; 21/02/2015
  5687 0000218E FEC8                <1> 	dec	al	 ; last head number 
  5688                              <1> 	;and	al, 0Fh
  5689 00002190 08E0                <1> 	or	al, ah	 ; lower 4 bits for head number
  5690                              <1> 	;
  5691 00002192 C645FE91            <1> 	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5692 00002196 8845FD              <1> 	mov	[CMD_BLOCK+5], al
  5693                              <1> 	;pop	bx
  5694 00002199 5B                  <1> 	pop	ebx
  5695 0000219A 29C0                <1> 	sub	eax, eax ; 21/02/2015
  5696 0000219C B004                <1> 	mov	al, 4 ; Physical sec per track from translated HDPT
  5697 0000219E 803D[E0610000]00    <1> 	cmp	byte [LBAMode], 0
  5698 000021A5 7702                <1> 	ja	short idrv1
  5699 000021A7 B00E                <1> 	mov	al, 14 ; Physical sec per track from standard HDPT
  5700                              <1> idrv1:
  5701                              <1> 	;xor	ah, ah
  5702                              <1> 	;add	bx, ax
  5703 000021A9 01C3                <1> 	add	ebx, eax ; 21/02/2015
  5704                              <1> 	;mov	al, [es:bx]
  5705                              <1> 			; sector number
  5706 000021AB 8A03                <1> 	mov	al, [ebx]
  5707 000021AD 8845F9              <1> 	mov	[CMD_BLOCK+1], al
  5708 000021B0 28C0                <1> 	sub	al, al
  5709 000021B2 8845FB              <1> 	mov	[CMD_BLOCK+3], al ; ZERO FLAGS
  5710 000021B5 E87B000000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  5711 000021BA 751E                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  5712 000021BC E816010000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  5713 000021C1 7517                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  5714                              <1> 	;call	CHECK_STATUS
  5715                              <1> 	;jmp	short CHECK_STATUS
  5716                              <1> ;INIT_EXIT:
  5717                              <1> 	;retn
  5718                              <1> 
  5719                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5720                              <1> 
  5721                              <1> ;----------------------------------------
  5722                              <1> ;	CHECK FIXED DISK STATUS 	:
  5723                              <1> ;----------------------------------------
  5724                              <1> CHECK_STATUS:
  5725 000021C3 E861010000          <1> 	call	CHECK_ST		; CHECK THE STATUS BYTE
  5726                              <1> 	;jnz	short CHECK_S1		; AN ERROR WAS FOUND
  5727                              <1> 	; 10/07/2022
  5728 000021C8 7510                <1> 	jnz	short CHECK_S2
  5729 000021CA A801                <1> 	test	al, ST_ERROR		; WERE THERE ANY OTHER ERRORS
  5730 000021CC 7405                <1> 	jz	short CHECK_S1		; NO ERROR REPORTED
  5731 000021CE E894010000          <1> 	call	CHECK_ER		; ERROR REPORTED
  5732                              <1> CHECK_S1:
  5733 000021D3 803D[CB610000]00    <1> 	cmp	byte [DISK_STATUS1], 0 	; SET STATUS FOR CALLER
  5734                              <1> CHECK_S2:
  5735                              <1> INIT_EXIT:	; 10/07/2022
  5736 000021DA C3                  <1> 	retn
  5737                              <1> 
  5738                              <1> ;----------------------------------------
  5739                              <1> ;	TEST DISK READY      (AH = 10H) :
  5740                              <1> ;----------------------------------------
  5741                              <1> 
  5742                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  5743 000021DB E8F7000000          <1> 	call	NOT_BUSY
  5744 000021E0 751C                <1> 	jnz	short TR_EX
  5745 000021E2 8A45FD              <1> 	mov	al, [CMD_BLOCK+5] 	; SELECT DRIVE
  5746 000021E5 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]
  5747 000021EC 80C206              <1> 	add	dl,6
  5748 000021EF EE                  <1> 	out	dx, al
  5749 000021F0 E834010000          <1> 	call	CHECK_ST		; CHECK STATUS ONLY
  5750 000021F5 7507                <1> 	jnz	short TR_EX
  5751 000021F7 C605[CB610000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; WIPE OUT DATA CORRECTED ERROR
  5752                              <1> TR_EX:	
  5753 000021FE C3                  <1> 	retn
  5754                              <1> 
  5755                              <1> ;----------------------------------------
  5756                              <1> ;	RECALIBRATE	     (AH = 11H) :
  5757                              <1> ;----------------------------------------
  5758                              <1> 
  5759                              <1> HDISK_RECAL:
  5760 000021FF C645FE10            <1>         mov	byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16
  5761 00002203 E82D000000          <1> 	call	COMMAND 		; START THE OPERATION
  5762 00002208 7523                <1> 	jnz	short RECAL_EXIT	; ERROR
  5763 0000220A E898000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION
  5764 0000220F 7407                <1> 	jz	short RECAL_X 		; TIME OUT ONE OK ?
  5765 00002211 E891000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION LONGER
  5766 00002216 7515                <1> 	jnz	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  5767                              <1> RECAL_X:
  5768 00002218 E8A6FFFFFF          <1> 	call	CHECK_STATUS
  5769 0000221D 803D[CB610000]40    <1> 	cmp	byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE
  5770 00002224 7507                <1> 	jne	short RECAL_EXIT	; IS OK
  5771 00002226 C605[CB610000]00    <1> 	mov	byte [DISK_STATUS1], 0
  5772                              <1> RECAL_EXIT:
  5773 0000222D 803D[CB610000]00    <1>         cmp	byte [DISK_STATUS1], 0
  5774 00002234 C3                  <1> 	retn
  5775                              <1> 
  5776                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5777                              <1> 
  5778                              <1> ;--------------------------------------------------------
  5779                              <1> ; COMMAND						:
  5780                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  5781                              <1> ; OUTPUT						:
  5782                              <1> ;	BL = STATUS					:
  5783                              <1> ;	BH = ERROR REGISTER				:
  5784                              <1> ;--------------------------------------------------------
  5785                              <1> 
  5786                              <1> COMMAND:
  5787                              <1> 	;push	ebx ; 10/07/2022	; WAIT FOR SEEK COMPLETE AND READY
  5788                              <1> 	;;mov	ecx, DELAY_2		; SET INITIAL DELAY BEFORE TEST
  5789                              <1> COMMAND1:
  5790                              <1> 	;;push	ecx			; SAVE LOOP COUNT
  5791 00002235 E8A1FFFFFF          <1> 	call	TST_RDY 		; CHECK DRIVE READY
  5792                              <1> 	;;pop	ecx
  5793                              <1> 	;pop	ebx ; 10/07/2022
  5794 0000223A 7418                <1> 	jz	short COMMAND2		; DRIVE IS READY
  5795 0000223C 803D[CB610000]80    <1>         cmp	byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  5796                              <1> 	;jz	short CMD_TIMEOUT
  5797                              <1> 	;;loop	COMMAND1		; KEEP TRYING FOR A WHILE
  5798                              <1> 	;jmp	short COMMAND4		; ITS NOT GOING TO GET READY
  5799 00002243 7507                <1> 	jne	short COMMAND4
  5800                              <1> CMD_TIMEOUT:
  5801 00002245 C605[CB610000]20    <1> 	mov	byte [DISK_STATUS1], BAD_CNTLR
  5802                              <1> COMMAND4:
  5803                              <1> 	;;pop	ebx ; 10/07/2022
  5804 0000224C 803D[CB610000]00    <1>         cmp	byte [DISK_STATUS1], 0	; SET CONDITION CODE FOR CALLER
  5805 00002253 C3                  <1> 	retn
  5806                              <1> COMMAND2:
  5807                              <1> 	;;pop	ebx ; 10/07/2022
  5808                              <1> 	;push	edi ; 10/07/2022
  5809 00002254 C605[C6610000]00    <1> 	mov	byte [HF_INT_FLAG], 0	; RESET INTERRUPT FLAG
  5810 0000225B FA                  <1> 	cli				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  5811 0000225C E4A1                <1> 	in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  5812                              <1> 	;and	al, 0BFh
  5813 0000225E 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  5814                              <1> 	;JMP	$+2
  5815                              <1> 	IODELAY
  2130 00002260 EB00                <2>  jmp short $+2
  2131 00002262 EB00                <2>  jmp short $+2
  5816 00002264 E6A1                <1> 	out	INTB01, al
  5817 00002266 E421                <1> 	in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  5818 00002268 24FB                <1> 	and	al, 0FBh 		; SECOND CHIP
  5819                              <1> 	;JMP	$+2
  5820                              <1> 	IODELAY
  2130 0000226A EB00                <2>  jmp short $+2
  2131 0000226C EB00                <2>  jmp short $+2
  5821 0000226E E621                <1> 	out	INTA01, al
  5822 00002270 FB                  <1> 	sti
  5823                              <1> 	;xor	edi, edi		; INDEX THE COMMAND TABLE
  5824                              <1> 	; 10/07/2022
  5825 00002271 31C9                <1> 	xor	ecx, ecx
  5826                              <1> 	;mov	dx, HF_PORT+1		; DISK ADDRESS
  5827 00002273 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]
  5828 0000227A FEC2                <1> 	inc	dl
  5829 0000227C F605[CD610000]C0    <1> 	test	byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION
  5830 00002283 7411                <1> 	jz	short COMMAND3
  5831 00002285 8A45FE              <1> 	mov	al, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  5832 00002288 24F0                <1> 	and	al, 0F0h 		; GET RID OF MODIFIERS
  5833 0000228A 3C20                <1> 	cmp	al, 20h			; 20H-40H IS READ, WRITE, VERIFY
  5834 0000228C 7208                <1> 	jb	short COMMAND3
  5835 0000228E 3C40                <1> 	cmp	al, 40h
  5836 00002290 7704                <1> 	ja	short COMMAND3
  5837 00002292 804DFE01            <1> 	or	byte [CMD_BLOCK+6], NO_RETRIES 
  5838                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  5839                              <1> COMMAND3:
  5840                              <1> 	;mov	al, [CMD_BLOCK+edi]	; GET THE COMMAND STRING BYTE
  5841                              <1> 	; 10/07/2022
  5842 00002296 8A440DF8            <1> 	mov	al, [CMD_BLOCK+ecx]
  5843 0000229A EE                  <1> 	out	dx, al			; GIVE IT TO CONTROLLER
  5844                              <1> 	IODELAY
  2130 0000229B EB00                <2>  jmp short $+2
  2131 0000229D EB00                <2>  jmp short $+2
  5845                              <1> 	;inc	edi			; NEXT BYTE IN COMMAND BLOCK
  5846                              <1> 	; 10/07/2022
  5847 0000229F 41                  <1> 	inc	ecx
  5848                              <1> 	;inc	dx			; NEXT DISK ADAPTER REGISTER
  5849 000022A0 42                  <1> 	inc	edx   ; 10/07/2022	
  5850                              <1> 	;cmp	di, 7 ; 01/01/2015	; ALL DONE?
  5851                              <1> 	;jne	short COMMAND3		; NO--GO DO NEXT ONE
  5852 000022A1 80F907              <1> 	cmp	cl, 7 ; 10/07/2022
  5853 000022A4 72F0                <1> 	jb	short COMMAND3
  5854                              <1> 	;pop	edi ; 10/07/2022
  5855 000022A6 C3                  <1> 	retn				; ZERO FLAG IS SET
  5856                              <1> 
  5857                              <1> ;CMD_TIMEOUT:
  5858                              <1> ;	mov	byte [DISK_STATUS1], BAD_CNTLR
  5859                              <1> ;COMMAND4:
  5860                              <1> ;	pop	ebx
  5861                              <1> ;	cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5862                              <1> ;	retn
  5863                              <1> 
  5864                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5865                              <1> 
  5866                              <1> ;----------------------------------------
  5867                              <1> ;	WAIT FOR INTERRUPT		:
  5868                              <1> ;----------------------------------------
  5869                              <1> ;WAIT:
  5870                              <1> _WAIT:
  5871 000022A7 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5872                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5873                              <1> 	;clc
  5874                              <1> 	;mov	ax, 9000h		; DEVICE WAIT INTERRUPT
  5875                              <1> 	;int	15h
  5876                              <1> 	;jc	short WT2		; DEVICE TIMED OUT
  5877                              <1> 	;mov	bl, DELAY_1		; SET DELAY COUNT
  5878                              <1> 
  5879                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  5880                              <1> 	;; 21/02/2015
  5881                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  5882                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  5883 000022A8 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  5884                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  5885                              <1> ;-----	WAIT LOOP
  5886                              <1> 
  5887                              <1> WT1:	
  5888                              <1> 	;test	byte [HF_INT_FLAG], 80h	; TEST FOR INTERRUPT
  5889 000022AD F605[C6610000]C0    <1> 	test 	byte [HF_INT_FLAG], 0C0h
  5890                              <1> 	;loopz	WT1
  5891 000022B4 7512                <1> 	jnz	short WT3		; INTERRUPT--LETS GO
  5892                              <1> 	;dec	bl
  5893                              <1> 	;jnz	short WT1		; KEEP TRYING FOR A WHILE
  5894                              <1> 
  5895                              <1> WT1_hi:
  5896 000022B6 E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  5897 000022B8 A810                <1> 	test	al, 10h			; transition on memory
  5898 000022BA 75FA                <1> 	jnz	short WT1_hi		; refresh.
  5899                              <1> WT1_lo:
  5900 000022BC E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  5901 000022BE A810                <1> 	test	al, 10h			
  5902 000022C0 74FA                <1> 	jz	short WT1_lo
  5903 000022C2 E2E9                <1> 	loop	WT1
  5904                              <1> 	;;or	bl, bl
  5905                              <1> 	;;jz	short WT2	
  5906                              <1> 	;;dec	bl
  5907                              <1> 	;;jmp	short WT1
  5908                              <1> 	;dec	bl
  5909                              <1> 	;jnz	short WT1	
  5910                              <1> WT2:	
  5911                              <1> 	; 10/07/2022
  5912                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5913 000022C4 B080                <1> 	mov	al, TIME_OUT
  5914 000022C6 EB07                <1> 	jmp	short WT4
  5915                              <1> WT3:
  5916                              <1> 	;mov	byte [DISK_STATUS1], 0
  5917                              <1> 	;mov	byte [HF_INT_FLAG], 0
  5918 000022C8 28C0                <1> 	sub	al, al ; 0
  5919 000022CA A2[C6610000]        <1> 	mov	byte [HF_INT_FLAG], al
  5920                              <1> WT4:
  5921                              <1> NB2:	
  5922 000022CF A2[CB610000]        <1> 	mov	byte [DISK_STATUS1], al
  5923                              <1> 
  5924                              <1> 	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5925 000022D4 20C0                <1> 	and	al, al
  5926                              <1> 	; zf = 0 -> time out, zf = 1 -> ok
  5927 000022D6 C3                  <1> 	retn
  5928                              <1> 
  5929                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5930                              <1> 
  5931                              <1> ;----------------------------------------
  5932                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  5933                              <1> ;----------------------------------------
  5934                              <1> NOT_BUSY:
  5935 000022D7 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5936                              <1> 	;push	ebx
  5937                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5938 000022D8 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]
  5939 000022DF 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  5940                              <1> 	;mov	bl, DELAY_1
  5941                              <1> 					; wait for 10 seconds
  5942                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  5943                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  5944                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  5945 000022E2 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  5946                              <1> 	;
  5947                              <1> 	;;mov	byte [wait_count], 0    ; Reset wait counter
  5948                              <1> NB1:	
  5949 000022E7 EC                  <1> 	in	al, dx			; CHECK STATUS
  5950                              <1> 	;test	al, ST_BUSY
  5951 000022E8 2480                <1> 	and	al, ST_BUSY
  5952                              <1> 	;loopnz NB1
  5953 000022EA 74E3                <1> 	jz	short NB2 ; al = 0	; NOT BUSY--LETS GO
  5954                              <1> 	;dec	bl			
  5955                              <1> 	;jnz	short NB1		; KEEP TRYING FOR A WHILE
  5956                              <1> 
  5957                              <1> NB1_hi: 
  5958 000022EC E461                <1> 	in	al, SYS1		; wait for hi to lo
  5959 000022EE A810                <1> 	test	al, 010h		; transition on memory
  5960 000022F0 75FA                <1> 	jnz	short NB1_hi		; refresh.
  5961                              <1> NB1_lo: 
  5962 000022F2 E461                <1> 	in	al, SYS1
  5963 000022F4 A810                <1> 	test	al, 010h
  5964 000022F6 74FA                <1> 	jz	short NB1_lo
  5965 000022F8 E2ED                <1> 	loop	NB1
  5966                              <1> 	;dec	bl
  5967                              <1> 	;jnz	short NB1
  5968                              <1> 	;
  5969                              <1> 	;;cmp	byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  5970                              <1> 	;;jb	short NB1
  5971                              <1> 	;
  5972                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5973                              <1> 	;jmp	short NB3
  5974 000022FA B080                <1> 	mov	al, TIME_OUT
  5975                              <1> ;NB2:	
  5976 000022FC EBD1                <1> 	jmp	short NB2 ; 10/07/2022
  5977                              <1> 
  5978                              <1> ;	;mov	byte [DISK_STATUS1], 0
  5979                              <1> ;;NB3:	
  5980                              <1> ;	;pop	ebx
  5981                              <1> ;	mov	[DISK_STATUS1], al	;;; will be set after return
  5982                              <1> ;	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5983                              <1> ;	or	al, al			; (zf = 0 --> timeout)
  5984                              <1> ;	retn
  5985                              <1> 
  5986                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5987                              <1> 
  5988                              <1> ;----------------------------------------
  5989                              <1> ;	WAIT FOR DATA REQUEST		:
  5990                              <1> ;----------------------------------------
  5991                              <1> WAIT_DRQ:
  5992                              <1> 	;mov	cx, DELAY_3
  5993                              <1> 	;mov	dx, HF_PORT+7
  5994 000022FE 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]
  5995 00002305 80C207              <1> 	add	dl, 7
  5996                              <1> 	;;mov	bl, WAIT_HDU_DRQ_HI	; 0
  5997                              <1> 	;mov	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  5998                              <1> 					; (but it is written as 2000
  5999                              <1> 					; micro seconds in ATORGS.ASM file
  6000                              <1> 					; of Award Bios - 1999, D1A0622)
  6001 00002308 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  6002                              <1> WQ_1:
  6003 0000230D EC                  <1> 	in	al, dx			; GET STATUS
  6004 0000230E A808                <1> 	test	al, ST_DRQ		; WAIT FOR DRQ
  6005 00002310 7516                <1> 	jnz	short WQ_OK
  6006                              <1> 	;loop	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  6007                              <1> WQ_hi:	
  6008 00002312 E461                <1> 	in	al, SYS1		; wait for hi to lo
  6009 00002314 A810                <1> 	test	al, 010h		; transition on memory
  6010 00002316 75FA                <1> 	jnz	short WQ_hi		; refresh.
  6011                              <1> WQ_lo:  
  6012 00002318 E461                <1> 	in	al, SYS1
  6013 0000231A A810                <1> 	test	al, 010h
  6014 0000231C 74FA                <1> 	jz	short WQ_lo
  6015 0000231E E2ED                <1> 	loop	WQ_1
  6016                              <1> 
  6017 00002320 C605[CB610000]80    <1> 	mov	byte [DISK_STATUS1], TIME_OUT ; ERROR
  6018 00002327 F9                  <1> 	stc
  6019                              <1> WQ_OK:
  6020 00002328 C3                  <1> 	retn
  6021                              <1> ;WQ_OK:
  6022                              <1> 	;clc
  6023                              <1> 	;retn
  6024                              <1> 
  6025                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6026                              <1> 
  6027                              <1> ;----------------------------------------
  6028                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  6029                              <1> ;----------------------------------------
  6030                              <1> CHECK_ST:
  6031                              <1> 	;mov	dx, HF_PORT+7		; GET THE STATUS
  6032 00002329 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]
  6033 00002330 80C207              <1> 	add	dl, 7
  6034 00002333 EC                  <1> 	in	al, dx
  6035 00002334 A2[C5610000]        <1> 	mov	[HF_STATUS], al
  6036                              <1> 	;mov	ah, 0
  6037 00002339 28E4                <1> 	sub	ah, ah ; 0
  6038 0000233B A880                <1> 	test	al, ST_BUSY		; IF STILL BUSY
  6039 0000233D 751A                <1> 	jnz	short CKST_EXIT		; REPORT OK
  6040 0000233F B4CC                <1> 	mov	ah, WRITE_FAULT
  6041 00002341 A820                <1> 	test 	al, ST_WRT_FLT		; CHECK FOR WRITE FAULT
  6042 00002343 7514                <1> 	jnz	short CKST_EXIT
  6043 00002345 B4AA                <1> 	mov	ah, NOT_RDY
  6044 00002347 A840                <1> 	test	al, ST_READY		; CHECK FOR NOT READY
  6045 00002349 740E                <1> 	jz	short CKST_EXIT
  6046 0000234B B440                <1> 	mov	ah, BAD_SEEK
  6047 0000234D A810                <1> 	test	al, ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  6048 0000234F 7408                <1> 	jz	short CKST_EXIT
  6049 00002351 B411                <1> 	mov	ah, DATA_CORRECTED
  6050 00002353 A804                <1> 	test	al, ST_CORRCTD		; CHECK FOR CORRECTED ECC
  6051 00002355 7502                <1> 	jnz	short CKST_EXIT
  6052                              <1> 	;mov	ah, 0
  6053 00002357 30E4                <1> 	xor	ah, ah ; 0
  6054                              <1> CKST_EXIT:
  6055 00002359 8825[CB610000]      <1> 	mov	[DISK_STATUS1], ah	; SET ERROR FLAG
  6056 0000235F 80FC11              <1> 	cmp	ah, DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  6057 00002362 7402                <1> 	je	short CKST_EX1
  6058                              <1> 	;cmp	ah, 0
  6059 00002364 20E4                <1> 	and	ah, ah
  6060                              <1> CKST_EX1:
  6061 00002366 C3                  <1> 	retn
  6062                              <1> 
  6063                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6064                              <1> 
  6065                              <1> ;----------------------------------------
  6066                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  6067                              <1> ;----------------------------------------
  6068                              <1> CHECK_ER:
  6069                              <1> 	;mov	dx, HF_PORT+1		; GET THE ERROR REGISTER
  6070 00002367 668B15[525C0000]    <1> 	mov	dx, [HF_PORT]		;
  6071 0000236E FEC2                <1> 	inc	dl
  6072 00002370 EC                  <1> 	in	al, dx
  6073                              <1> 	; 10/07/2022
  6074                              <1> 	;mov	[HF_ERROR], al
  6075                              <1> 	;push	ebx	; 21/02/2015
  6076 00002371 29C9                <1> 	sub	ecx, ecx
  6077                              <1> 	;mov	ecx, 8			; TEST ALL 8 BITS
  6078 00002373 B108                <1> 	mov	cl, 8
  6079                              <1> CK1:	
  6080 00002375 D0E0                <1> 	shl	al, 1			; MOVE NEXT ERROR BIT TO CARRY
  6081 00002377 7202                <1> 	jc	short CK2		; FOUND THE ERROR
  6082 00002379 E2FA                <1> 	loop	CK1			; KEEP TRYING
  6083                              <1> CK2:
  6084                              <1> 	;mov	ebx, ERR_TBL		; COMPUTE ADDRESS OF
  6085                              <1> 	;add	ebx, ecx		; ERROR CODE
  6086 0000237B 81C1[485C0000]      <1> 	add	ecx, ERR_TBL ; 10/07/2022	
  6087                              <1> 
  6088                              <1> 	;;;mov	ah, byte [cs:bx]	; GET ERROR CODE
  6089                              <1> 	;;mov	ah, [bx]
  6090                              <1> 	;mov	ah, [ebx] ; 21/02/2015
  6091 00002381 8A21                <1> 	mov	ah, [ecx]	
  6092                              <1> CKEX:
  6093 00002383 8825[CB610000]      <1> 	mov	[DISK_STATUS1], ah	; SAVE ERROR CODE
  6094                              <1> 	; 10/07/2022
  6095                              <1> 	;pop	ebx
  6096                              <1> 	;;cmp	ah, 0
  6097                              <1> 	;and	ah, ah
  6098 00002389 C3                  <1> 	retn
  6099                              <1> 
  6100                              <1> ;--------------------------------------------------------
  6101                              <1> ; CHECK_DMA						:
  6102                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  6103                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  6104                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  6105                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  6106                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  6107                              <1> ;  -ERROR OTHERWISE					:
  6108                              <1> ;--------------------------------------------------------
  6109                              <1> 
  6110                              <1> 	; 11/07/2022
  6111                              <1> 	; (not needed for hard disks and 32 bit OS)
  6112                              <1> 	;
  6113                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6114                              <1> ;CHECK_DMA:
  6115                              <1> ;	;;push	ax			; SAVE REGISTERS
  6116                              <1> ;	;; 24/12/2021
  6117                              <1> ;	;;push	eax
  6118                              <1> ;	;mov	ax, 8000h		; AH = MAX # SECTORS
  6119                              <1> ;					; AL = MAX OFFSET
  6120                              <1> ;	; 10/07/2022
  6121                              <1> ;	;test	byte [CMD_BLOCK+6], ECC_MODE
  6122                              <1> ;	;jz	short CKD1
  6123                              <1> ;	;mov	ax, 7F04h		; ECC IS 4 MORE BYTES
  6124                              <1> ;CKD1:	
  6125                              <1> ;	;cmp	ah, [CMD_BLOCK+1]	; NUMBER OF SECTORS
  6126                              <1> ;	;ja	short CKDOK		; IT WILL FIT
  6127                              <1> ;	;jb	short CKDERR		; TOO MANY
  6128                              <1> ;	
  6129                              <1> ;	cmp	byte [CMD_BLOCK+1], 80h
  6130                              <1> ;	jb	short CKDOK
  6131                              <1> ;	ja	short CKDERR
  6132                              <1> ;	;cmp	al, bl			; CHECK OFFSET ON MAX SECTORS
  6133                              <1> ;	;jb	short CKDERR		; ERROR
  6134                              <1> ;CKD2:
  6135                              <1> ;	or	bl, bl
  6136                              <1> ;	jz	short CKDR
  6137                              <1> ;	
  6138                              <1> ;;CKDOK:	
  6139                              <1> ;	;clc				; CLEAR CARRY
  6140                              <1> ;	;;pop	ax
  6141                              <1> ;	;; 24/12/2021
  6142                              <1> ;	;pop	eax
  6143                              <1> ;	;retn				; NORMAL RETURN
  6144                              <1> ;CKDERR: 
  6145                              <1> ;	stc				; INDICATE ERROR
  6146                              <1> ;	mov	byte [DISK_STATUS1], DMA_BOUNDARY
  6147                              <1> ;	;;pop	ax
  6148                              <1> ;	;; 24/12/2021
  6149                              <1> ;	;pop	eax	
  6150                              <1> ;	retn
  6151                              <1> ;
  6152                              <1> ;	; 10/07/2022
  6153                              <1> ;CKDOK:
  6154                              <1> ;	clc
  6155                              <1> ;CKDR:
  6156                              <1> ;	retn
  6157                              <1> 
  6158                              <1> ;----------------------------------------
  6159                              <1> ;	SET UP EBX-> DISK PARMS	        :
  6160                              <1> ;----------------------------------------
  6161                              <1> 					
  6162                              <1> ; INPUT -> DL = 0 based drive number
  6163                              <1> ; OUTPUT -> EBX = disk parameter table address
  6164                              <1> 
  6165                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6166                              <1> 
  6167                              <1> GET_VEC:
  6168                              <1> 	;sub	ax, ax			; GET DISK PARAMETER ADDRESS
  6169                              <1> 	;mov	es, ax
  6170                              <1> 	;test	dl, 1
  6171                              <1> 	;jz	short GV_0
  6172                              <1> ;	les	bx, [HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  6173                              <1> ;	jmp	short GV_EXIT
  6174                              <1> ;GV_0:
  6175                              <1> ;	les 	bx,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  6176                              <1> ;
  6177 0000238A 31DB                <1> 	xor	ebx, ebx
  6178 0000238C 88D3                <1> 	mov	bl, dl
  6179                              <1> 	;02/01/2015
  6180                              <1> 	;xor	bh, bh
  6181                              <1> 	;shl	bl, 1			; port address offset
  6182                              <1> 	;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  6183                              <1> 	;shl	bl, 1			; dpt pointer offset
  6184 0000238E C0E302              <1> 	shl	bl, 2
  6185                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  6186 00002391 81C3[D0610000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  6187                              <1> 	;push	word [bx+2]		; dpt segment
  6188                              <1> 	;pop	es
  6189                              <1> 	;mov	bx, [bx]		; dpt offset
  6190 00002397 8B1B                <1> 	mov	ebx, [ebx]		
  6191                              <1> ;GV_EXIT:
  6192 00002399 C3                  <1> 	retn
  6193                              <1> 
  6194                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6195                              <1> hdc1_int: ; 21/02/2015
  6196                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  6197                              <1> ;								:
  6198                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6199                              <1> ;								:
  6200                              <1> ;----------------------------------------------------------------
  6201                              <1> 
  6202                              <1> ; 22/12/2014
  6203                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  6204                              <1> ;	 '11/15/85'
  6205                              <1> ; AWARD BIOS 1999 (D1A0622) 
  6206                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  6207                              <1> 
  6208                              <1> ;int_76h:
  6209                              <1> HD_INT:
  6210                              <1> 	;push	ax
  6211                              <1> 	; 24/12/2021
  6212 0000239A 50                  <1> 	push	eax
  6213 0000239B 1E                  <1> 	push	ds
  6214                              <1> 	;CALL	DDS
  6215                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6216 0000239C 66B81000            <1> 	mov	ax, KDATA
  6217 000023A0 8ED8                <1> 	mov 	ds, ax
  6218                              <1> 	;
  6219                              <1> 	;;MOV	@HF_INT_FLAG, 0FFH	; ALL DONE
  6220                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  6221 000023A2 C605[C6610000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  6222                              <1> 	;
  6223                              <1> 	;push	dx
  6224                              <1> 	; 24/12/2021
  6225 000023A9 52                  <1> 	push	edx
  6226 000023AA 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  6227                              <1> 					; Clear Controller
  6228                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  6229 000023AE EC                  <1> 	in	al, dx			;
  6230                              <1> 	;pop	dx
  6231                              <1> 	; 24/12/2021
  6232 000023AF 5A                  <1> 	pop	edx
  6233                              <1> 	NEWIODELAY
  2135 000023B0 E6EB                <2>  out 0EBh,al
  6234                              <1> 	;
  6235 000023B2 B020                <1> 	mov	al, EOI			; NON-SPECIFIC END OF INTERRUPT
  6236 000023B4 E6A0                <1> 	out	INTB00, al		; FOR CONTROLLER #2
  6237                              <1> 	;JMP	$+2			; WAIT
  6238                              <1> 	NEWIODELAY
  2135 000023B6 E6EB                <2>  out 0EBh,al
  6239 000023B8 E620                <1> 	out	INTA00, al		; FOR CONTROLLER #1
  6240 000023BA 1F                  <1> 	pop	ds
  6241                              <1> 	;sti				; RE-ENABLE INTERRUPTS
  6242                              <1> 	;mov	ax, 9100h		; DEVICE POST
  6243                              <1> 	;int	15h			; INTERRUPT
  6244                              <1> irq15_iret: ; 25/02/2015
  6245                              <1> 	;pop	ax
  6246                              <1> 	; 24/12/2021
  6247 000023BB 58                  <1> 	pop	eax
  6248 000023BC CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  6249                              <1> 
  6250                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6251                              <1> hdc2_int: ; 21/02/2015
  6252                              <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) ----------------------
  6253                              <1> ;								:
  6254                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6255                              <1> ;								:
  6256                              <1> ;----------------------------------------------------------------
  6257                              <1> 
  6258                              <1> ;int_77h:
  6259                              <1> HD1_INT:
  6260                              <1> 	;push	ax
  6261                              <1> 	; 24/12/2021
  6262 000023BD 50                  <1> 	push	eax
  6263                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  6264                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  6265 000023BE B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  6266 000023C0 E6A0                <1> 	out	0A0h, al
  6267 000023C2 EB00                <1>         jmp short $+2
  6268 000023C4 EB00                <1> 	jmp short $+2
  6269 000023C6 E4A0                <1> 	in	al, 0A0h
  6270 000023C8 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  6271 000023CA 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  6272                              <1> 	;
  6273 000023CC 1E                  <1> 	push	ds
  6274                              <1> 	;CALL	DDS
  6275                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6276 000023CD 66B81000            <1> 	mov	ax, KDATA
  6277 000023D1 8ED8                <1> 	mov 	ds, ax
  6278                              <1> 	;
  6279                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  6280                              <1>         ;or	byte [CS:HF_INT_FLAG], 0C0h 
  6281 000023D3 800D[C6610000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  6282                              <1> 	;
  6283                              <1> 	;push	dx
  6284                              <1> 	; 24/12/2021
  6285 000023DA 52                  <1> 	push	edx
  6286 000023DB 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  6287                              <1> 					; Clear Controller (Award BIOS 1999)
  6288 000023DF EBCD                <1> 	jmp	short Clear_IRQ1415
  6289                              <1> 
  6290                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  6291                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  6292                              <1> 
  6293                              <1> ;////////////////////////////////////////////////////////////////////
  6294                              <1> ;; END OF DISK I/O SYTEM ///
  2049                                  %include 'memory.inc'  ; 09/03/2015
  2050                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2051                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.22) - MEMORY.INC
  2052                              <1> ; Last Modification: 17/07/2022
  2053                              <1> ;
  2054                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2055                              <1> 
  2056                              <1> ; Ref: Retro UNIX 386 v1.1, Kernel v0.2.1.6 - MEMORY.INC (17/07/2022)
  2057                              <1> 
  2058                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2059                              <1> 
  2060                              <1> ;;04/11/2014 (unix386.s)	
  2061                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2062                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2063                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2064                              <1> ;;
  2065                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2066                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2067                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2068                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2069                              <1> 
  2070                              <1> ; 27/04/2015
  2071                              <1> ; 09/03/2015
  2072                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2073                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2074                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2075                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2076                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2077                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2078                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2079                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2080                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2081                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2082                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2083                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2084                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2085                              <1> SWP_DISK_READ_ERR 	   equ 40
  2086                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2087                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2088                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2089                              <1> SWP_DISK_WRITE_ERR         equ 44
  2090                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2091                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2092                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2093                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2094                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2095                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2096                              <1> 					; (Indicates that the page is not allocated
  2097                              <1> 					; for the process, it is a shared or system
  2098                              <1>                                         ; page, it must not be deallocated!)
  2099                              <1> ; 14/12/2020
  2100                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2101                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2102                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2103                              <1> 				; (Out of memory allocation table)	
  2104                              <1> ;
  2105                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2106                              <1> ;;
  2107                              <1> ;; 10/10/2014
  2108                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2109                              <1> ;;
  2110                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2111                              <1> ;;	(virtual address = physical address)
  2112                              <1> ;; KERNEL PAGE TABLES:
  2113                              <1> ;;	Kernel page directory and all page tables are
  2114                              <1> ;;	on memory as initialized, as equal to physical memory
  2115                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2116                              <1> ;;
  2117                              <1> ;;	what for: User pages may be swapped out, when accessing
  2118                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2119                              <1> ;;	kernel would have to swap it in! But it is also may be
  2120                              <1> ;;	in use by a user process. (In system/kernel mode
  2121                              <1> ;;	kernel can access all memory pages even if they are
  2122                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2123                              <1> ;;	cause conflicts.) 
  2124                              <1> ;;	
  2125                              <1> ;;	As result of these conditions,
  2126                              <1> ;;	all kernel pages must be initialized as equal to 
  2127                              <1> ;;	physical layout for preventing page faults. 
  2128                              <1> ;;	Also, calling "allocate page" procedure after
  2129                              <1> ;;	a page fault can cause another page fault (double fault)
  2130                              <1> ;;	if all kernel page tables would not be initialized.
  2131                              <1> ;;
  2132                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2133                              <1> ;;	memory allocation table. (double word aligned)
  2134                              <1> ;;
  2135                              <1> ;;	[next_page] = first/next free space to be searched
  2136                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2137                              <1> ;;
  2138                              <1> ;;	[last_page] = End of memory (users space), as offset
  2139                              <1> ;;	to memory allocation table. (double word aligned)
  2140                              <1> ;;
  2141                              <1> ;; USER PAGE TABLES:
  2142                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2143                              <1> ;;		'ready only' marked copies of the 
  2144                              <1> ;;		parent process's page table entries (for
  2145                              <1> ;;		same physical memory).
  2146                              <1> ;;		(A page will be copied to a new page after
  2147                              <1> ;;		 if it causes R/W page fault.)
  2148                              <1> ;;
  2149                              <1> ;;	Every user process has own (different)
  2150                              <1> ;;	page directory and page tables.	
  2151                              <1> ;;
  2152                              <1> ;;	Code starts at virtual address 0, always.
  2153                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2154                              <1> ;;	(Programs can be written/developed as simple
  2155                              <1> ;;	 flat memory programs.)
  2156                              <1> ;;
  2157                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2158                              <1> ;;	Memory page will be allocated by kernel only 
  2159                              <1> ;;		(in kernel/system mode only).
  2160                              <1> ;;	* After a
  2161                              <1> ;;	  - 'not present' page fault
  2162                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2163                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2164                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2165                              <1> ;;	  request by running process.
  2166                              <1> ;;	* While creating a process, allocating a new buffer,
  2167                              <1> ;;	  new page tables etc.
  2168                              <1> ;;
  2169                              <1> ;;	At first,
  2170                              <1> ;;	- 'allocate page' procedure will be called;
  2171                              <1> ;,	   if it will return with a valid (>0) physical address
  2172                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2173                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2174                              <1> ;;	- 'allocate page' will be called for allocating page
  2175                              <1> ;;	   directory, page table and running space (data/code).
  2176                              <1> ;;	- every successful 'allocate page' call will decrease
  2177                              <1> ;;	  'free_pages' count (pointer).
  2178                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2179                              <1> ;;	  if 'free_pages' points to a ZERO.
  2180                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2181                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2182                              <1> ;;	  error except errors caused by attribute conflicts.
  2183                              <1> ;;	 (swapper functions)	 
  2184                              <1> ;;					
  2185                              <1> ;;	At second,
  2186                              <1> ;;	- page directory entry will be updated then page table
  2187                              <1> ;;	  entry will be updated.		
  2188                              <1> ;;
  2189                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2190                              <1> ;;	- M.A.T. has a size according to available memory as
  2191                              <1> ;;	  follows:
  2192                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2193                              <1> ;;		  - a bit with value of 0 means allocated page
  2194                              <1> ;;		  - a bit with value of 1 means a free page
  2195                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2196                              <1> ;;	  depending on M.A.T.
  2197                              <1> ;;		(NOTE: Free page count will not be checked
  2198                              <1> ;;		again -on M.A.T.- after initialization. 
  2199                              <1> ;;		Kernel will trust on initial count.)
  2200                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2201                              <1> ;;	  and it will be increased by deallocation procedures.
  2202                              <1> ;;	
  2203                              <1> ;;	- Available memory will be calculated during
  2204                              <1> ;;	  the kernel's initialization stage (in real mode).
  2205                              <1> ;;	  Memory allocation table and kernel page tables 
  2206                              <1> ;;	  will be formatted/sized as result of available
  2207                              <1> ;;	  memory calculation before paging is enabled.
  2208                              <1> ;;
  2209                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2210                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2211                              <1> ;;	- Memory allocation for kernel page directory size 
  2212                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2213                              <1> ;;	  for page tables)
  2214                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2215                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2216                              <1> ;;	- User (available) space will be started 
  2217                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2218                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2219                              <1> ;;	  memory allocation table and kernel's page directory
  2220                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2221                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2222                              <1> ;; 	  for buffers.
  2223                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2224                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2225                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2226                              <1> ;;
  2227                              <1> ;; For 1GB Available Memory:
  2228                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2229                              <1> ;;	- Memory allocation for kernel page directory size 
  2230                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2231                              <1> ;;	  for page tables)
  2232                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2233                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2234                              <1> ;;	- User (available) space will be started 
  2235                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2236                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2237                              <1> ;;	  memory allocation table and kernel's page directory
  2238                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2239                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2240                              <1> ;; 	  for buffers.
  2241                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2242                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2243                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2244                              <1> ;;
  2245                              <1> ;;
  2246                              <1> 
  2247                              <1> ;;************************************************************************************
  2248                              <1> ;; 
  2249                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2250                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2251                              <1> 
  2252                              <1> ;; Main factor: "sys fork" system call 
  2253                              <1> ;;	
  2254                              <1> ;; 		FORK
  2255                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2256                              <1> ;;  writable pages ---->|
  2257                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2258                              <1> ;; 
  2259                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2260                              <1> ;; 
  2261                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2262                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2263                              <1> ;;       -while R/W bit is 0-. 
  2264                              <1> ;; 
  2265                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2266                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2267                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2268                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2269                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2270                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2271                              <1> ;; 
  2272                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2273                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2274                              <1> ;;   Parent's PTE attributes are not changed.
  2275                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2276                              <1> ;;    destroy/mix previous fork result).
  2277                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2278                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2279                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2280                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2281                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2282                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2283                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2284                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2285                              <1> ;; 
  2286                              <1> ;; !? WHAT FOR (duplication after duplication):
  2287                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2288                              <1> ;; program/executable code continues from specified location as child process, 
  2289                              <1> ;; returns back previous code location as parent process, every child after 
  2290                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2291                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2292                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2293                              <1> ;; was copied to child's process segment (all of code and data) according to
  2294                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2295                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2296                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2297                              <1> ;; (complete running image of parent process) to the child process; 
  2298                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2299                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2300                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2301                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2302                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2303                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2304                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2305                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2306                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2307                              <1> ;; for sharing same read only pages between parent and child processes.
  2308                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2309                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2310                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2311                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2312                              <1> ;; -deallocation problem-.
  2313                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2314                              <1> ;; 
  2315                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2316                              <1> ;; # Page fault handler will do those:
  2317                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2318                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2319                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2320                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2321                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2322                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2323                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2324                              <1> ;;     to child process.)	
  2325                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2326                              <1> ;; # Page fault handler will do those:
  2327                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2328                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2329                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2330                              <1> ;;     address or not. 
  2331                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2332                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2333                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2334                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2335                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2336                              <1> ;; 
  2337                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2338                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2339                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2340                              <1> ;;       duplication method details, it is not possible multiple child processes
  2341                              <1> ;;       were using same page with duplicated PTEs.
  2342                              <1> ;; 
  2343                              <1> ;;************************************************************************************   
  2344                              <1> 
  2345                              <1> ;; 08/10/2014
  2346                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2347                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2348                              <1> 
  2349                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2350                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2351                              <1> ;; (25/08/2014, Revision: 5057) file 
  2352                              <1> ;; by KolibriOS Team (2004-2012)
  2353                              <1> 
  2354                              <1> allocate_page:
  2355                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2356                              <1> 	; 01/07/2015
  2357                              <1> 	; 05/05/2015
  2358                              <1> 	; 30/04/2015
  2359                              <1> 	; 16/10/2014
  2360                              <1> 	; 08/10/2014
  2361                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2362                              <1> 	;
  2363                              <1> 	; INPUT -> none
  2364                              <1> 	;
  2365                              <1> 	; OUTPUT ->
  2366                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2367                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2368                              <1> 	;
  2369                              <1> 	;	CF = 1 and EAX = 0 
  2370                              <1> 	; 		   if there is not a free page to be allocated	
  2371                              <1> 	;
  2372                              <1> 	; Modified Registers -> none (except EAX)
  2373                              <1> 	;
  2374 000023E1 A1[40610000]        <1> 	mov	eax, [free_pages]
  2375 000023E6 21C0                <1> 	and	eax, eax
  2376 000023E8 7438                <1> 	jz	short out_of_memory
  2377                              <1> 	;
  2378 000023EA 53                  <1> 	push	ebx
  2379 000023EB 51                  <1> 	push	ecx
  2380                              <1> 	;
  2381 000023EC BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2382 000023F1 89D9                <1> 	mov	ecx, ebx
  2383                              <1>  				     ; NOTE: 32 (first_page) is initial
  2384                              <1> 				     ; value of [next_page].
  2385                              <1> 				     ; It points to the first available
  2386                              <1> 				     ; page block for users (ring 3) ...	
  2387                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2388                              <1> 				     ; (at the of the first 4 MB)		
  2389 000023F3 031D[44610000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2390                              <1> 				 ; next_free_page >> 5
  2391 000023F9 030D[48610000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2392                              <1> 				 ; (total_pages - 1) >> 5
  2393                              <1> al_p_scan:
  2394 000023FF 39CB                <1> 	cmp	ebx, ecx
  2395 00002401 770A                <1> 	ja	short al_p_notfound
  2396                              <1> 	;
  2397                              <1> 	; 01/07/2015
  2398                              <1> 	; AMD64 Architecture Programmers Manual
  2399                              <1> 	; Volume 3:
  2400                              <1> 	; General-Purpose and System Instructions
  2401                              <1> 	;
  2402                              <1> 	; BSF - Bit Scan Forward
  2403                              <1> 	;
  2404                              <1> 	;   Searches the value in a register or a memory location
  2405                              <1> 	;   (second operand) for the least-significant set bit. 
  2406                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2407                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2408                              <1> 	;   register (first operand). If the second operand contains 0, 
  2409                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2410                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2411                              <1> 	;   of the searched value
  2412                              <1> 	;
  2413 00002403 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2414                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2415                              <1> 			   ; loads the destination with an index to
  2416                              <1> 			   ; first set bit. (0 -> 31) 
  2417                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2418 00002406 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2419                              <1> 			 ;
  2420                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2421                              <1> 			 ;	  with value of 1 means 
  2422                              <1> 			 ;	  the corresponding page is free 
  2423                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2424 00002408 83C304              <1> 	add	ebx, 4
  2425                              <1> 			 ; We return back for searching next page block
  2426                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2427                              <1> 			 ;	 we always will find at least 1 free page here.
  2428 0000240B EBF2                <1>         jmp     short al_p_scan
  2429                              <1> 	;
  2430                              <1> al_p_notfound:
  2431 0000240D 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2432 00002413 890D[44610000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2433                              <1> 				 ; (deallocate_page procedure will change it)
  2434 00002419 31C0                <1> 	xor	eax, eax
  2435 0000241B A3[40610000]        <1> 	mov	[free_pages], eax ; 0
  2436 00002420 59                  <1> 	pop	ecx
  2437 00002421 5B                  <1> 	pop	ebx
  2438                              <1> 	;
  2439                              <1> ; 24/12/2021
  2440                              <1> ; ('swap_out' procedure call is disabled)
  2441                              <1> 
  2442                              <1> out_of_memory:
  2443                              <1> ;	call	swap_out
  2444                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2445                              <1> ;	;
  2446                              <1> ;	sub 	eax, eax ; 0
  2447 00002422 F9                  <1> 	stc
  2448 00002423 C3                  <1> 	retn
  2449                              <1> 
  2450                              <1> al_p_found:
  2451 00002424 89D9                <1> 	mov	ecx, ebx
  2452 00002426 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2453 0000242C 890D[44610000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2454                              <1> 				 ; address/offset (to the next)
  2455 00002432 FF0D[40610000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2456                              <1> 	;
  2457 00002438 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2458                              <1> 				 ; is copied into the Carry Flag and then cleared
  2459                              <1> 				 ; in the destination.
  2460                              <1> 				 ;
  2461                              <1> 				 ; Reset the bit which is corresponding to the 
  2462                              <1> 				 ; (just) allocated page.
  2463                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2464 0000243B C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2465 0000243E 01C8                <1> 	add	eax, ecx	 ; = page number
  2466 00002440 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2467                              <1> 	; EAX = physical address of memory page
  2468                              <1> 	;
  2469                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2470                              <1> 	;       according to this EAX value...
  2471 00002443 59                  <1> 	pop	ecx
  2472 00002444 5B                  <1> 	pop	ebx
  2473                              <1> al_p_ok:
  2474 00002445 C3                  <1> 	retn
  2475                              <1> 
  2476                              <1> make_page_dir:
  2477                              <1> 	; 18/04/2015
  2478                              <1> 	; 12/04/2015
  2479                              <1> 	; 23/10/2014
  2480                              <1> 	; 16/10/2014
  2481                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2482                              <1> 	;
  2483                              <1> 	; INPUT ->
  2484                              <1> 	;	none
  2485                              <1> 	; OUTPUT ->
  2486                              <1> 	;	(EAX = 0)
  2487                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2488                              <1> 	;	cf = 0 ->
  2489                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2490                              <1> 	;		  process/user.
  2491                              <1> 	;
  2492                              <1> 	; Modified Registers -> EAX
  2493                              <1> 	;
  2494 00002446 E896FFFFFF          <1> 	call	allocate_page
  2495 0000244B 7216                <1> 	jc	short mkpd_error
  2496                              <1> 	;
  2497 0000244D A3[53650000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2498                              <1> 				  ; (Physical address)
  2499                              <1> clear_page:
  2500                              <1> 	; 18/04/2015
  2501                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2502                              <1> 	;
  2503                              <1> 	; INPUT ->
  2504                              <1> 	;	EAX = physical address of the page
  2505                              <1> 	; OUTPUT ->
  2506                              <1> 	;	all bytes of the page will be cleared
  2507                              <1> 	;
  2508                              <1> 	; Modified Registers -> none
  2509                              <1> 	;
  2510 00002452 57                  <1> 	push	edi
  2511 00002453 51                  <1> 	push	ecx
  2512 00002454 50                  <1> 	push	eax
  2513 00002455 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2514 0000245A 89C7                <1> 	mov	edi, eax
  2515 0000245C 31C0                <1> 	xor	eax, eax
  2516 0000245E F3AB                <1> 	rep	stosd
  2517 00002460 58                  <1> 	pop	eax
  2518 00002461 59                  <1> 	pop	ecx
  2519 00002462 5F                  <1> 	pop	edi
  2520                              <1> mkpd_error:
  2521                              <1> mkpt_error:
  2522 00002463 C3                  <1> 	retn
  2523                              <1> 
  2524                              <1> make_page_table:
  2525                              <1> 	; 23/06/2015
  2526                              <1> 	; 18/04/2015
  2527                              <1> 	; 12/04/2015
  2528                              <1> 	; 16/10/2014
  2529                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2530                              <1> 	;
  2531                              <1> 	; INPUT ->
  2532                              <1> 	;	EBX = virtual (linear) address
  2533                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2534                              <1> 	;	      (higher 20 bits must be ZERO)
  2535                              <1> 	;	      (bit 0 must be 1)	 
  2536                              <1> 	;	u.pgdir = page directory (physical) address
  2537                              <1> 	; OUTPUT ->
  2538                              <1> 	;	EDX = Page directory entry address
  2539                              <1> 	;	EAX = Page table address
  2540                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2541                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2542                              <1> 	;
  2543                              <1> 	; Modified Registers -> EAX, EDX
  2544                              <1> 	;
  2545 00002464 E878FFFFFF          <1> 	call	allocate_page
  2546 00002469 72F8                <1> 	jc	short mkpt_error
  2547 0000246B E811000000          <1> 	call	set_pde	
  2548 00002470 EBE0                <1> 	jmp	short clear_page
  2549                              <1> 
  2550                              <1> make_page:
  2551                              <1> 	; 24/07/2015
  2552                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2553                              <1> 	;
  2554                              <1> 	; INPUT ->
  2555                              <1> 	;	EBX = virtual (linear) address
  2556                              <1> 	;	ECX = page attributes (lower 12 bits)
  2557                              <1> 	;	      (higher 20 bits must be ZERO)
  2558                              <1> 	;	      (bit 0 must be 1)	 
  2559                              <1> 	;	u.pgdir = page directory (physical) address
  2560                              <1> 	; OUTPUT ->
  2561                              <1> 	;	EBX = Virtual address
  2562                              <1> 	;	(EDX = PTE value)
  2563                              <1> 	;	EAX = Physical address
  2564                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2565                              <1> 	;
  2566                              <1> 	; Modified Registers -> EAX, EDX
  2567                              <1> 	;
  2568 00002472 E86AFFFFFF          <1> 	call	allocate_page
  2569 00002477 7207                <1> 	jc	short mkp_err
  2570 00002479 E821000000          <1> 	call	set_pte	
  2571 0000247E 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2572                              <1> mkp_err:
  2573 00002480 C3                  <1> 	retn
  2574                              <1> 
  2575                              <1> set_pde:	; Set page directory entry (PDE)
  2576                              <1> 	; 20/07/2015
  2577                              <1> 	; 18/04/2015
  2578                              <1> 	; 12/04/2015
  2579                              <1> 	; 23/10/2014
  2580                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2581                              <1> 	;
  2582                              <1> 	; INPUT ->
  2583                              <1> 	;	EAX = physical address
  2584                              <1> 	;	      (use present value if EAX = 0)
  2585                              <1> 	;	EBX = virtual (linear) address
  2586                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2587                              <1> 	;	      (higher 20 bits must be ZERO)
  2588                              <1> 	;	      (bit 0 must be 1)	 
  2589                              <1> 	;	u.pgdir = page directory (physical) address
  2590                              <1> 	; OUTPUT ->
  2591                              <1> 	;	EDX = PDE address
  2592                              <1> 	;	EAX = page table address (physical)
  2593                              <1> 	;	;(CF=1 -> Invalid page address)
  2594                              <1> 	;
  2595                              <1> 	; Modified Registers -> EDX
  2596                              <1> 	;
  2597 00002481 89DA                <1> 	mov	edx, ebx
  2598 00002483 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2599 00002486 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2600 00002489 0315[53650000]      <1> 	add	edx, [u.pgdir]
  2601                              <1> 	;
  2602 0000248F 21C0                <1> 	and	eax, eax
  2603 00002491 7506                <1> 	jnz	short spde_1
  2604                              <1> 	;
  2605 00002493 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2606                              <1> 	;test	al, 1
  2607                              <1> 	;jz	short spde_2
  2608 00002495 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2609                              <1> spde_1:
  2610                              <1> 	;and	cx, 0FFFh
  2611 00002499 8902                <1> 	mov	[edx], eax
  2612 0000249B 66090A              <1> 	or	[edx], cx
  2613 0000249E C3                  <1> 	retn
  2614                              <1> ;spde_2: ; error
  2615                              <1> ;	stc
  2616                              <1> ;	retn
  2617                              <1> 
  2618                              <1> set_pte:	; Set page table entry (PTE)
  2619                              <1> 	; 24/07/2015
  2620                              <1> 	; 20/07/2015
  2621                              <1> 	; 23/06/2015
  2622                              <1> 	; 18/04/2015
  2623                              <1> 	; 12/04/2015
  2624                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2625                              <1> 	;
  2626                              <1> 	; INPUT ->
  2627                              <1> 	;	EAX = physical page address
  2628                              <1> 	;	      (use present value if EAX = 0)
  2629                              <1> 	;	EBX = virtual (linear) address
  2630                              <1> 	;	ECX = page attributes (lower 12 bits)
  2631                              <1> 	;	      (higher 20 bits must be ZERO)
  2632                              <1> 	;	      (bit 0 must be 1)	 
  2633                              <1> 	;	u.pgdir = page directory (physical) address
  2634                              <1> 	; OUTPUT ->
  2635                              <1> 	;	EAX = physical page address
  2636                              <1> 	;	(EDX = PTE value)
  2637                              <1> 	;	EBX = virtual address
  2638                              <1> 	;
  2639                              <1> 	;	CF = 1 -> error
  2640                              <1> 	;
  2641                              <1> 	; Modified Registers -> EAX, EDX
  2642                              <1> 	;
  2643 0000249F 50                  <1> 	push	eax
  2644 000024A0 A1[53650000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2645 000024A5 E837000000          <1> 	call 	get_pde
  2646                              <1> 		; EDX = PDE address
  2647                              <1> 		; EAX = PDE value
  2648 000024AA 5A                  <1> 	pop	edx ; physical page address
  2649 000024AB 722A                <1> 	jc	short spte_err ; PDE not present
  2650                              <1> 	;
  2651 000024AD 53                  <1> 	push	ebx ; 24/07/2015
  2652 000024AE 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2653                              <1> 			    ; EDX = PT address (physical)	
  2654 000024B2 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2655 000024B5 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2656                              <1> 			 ; clear higher 10 bits (PD bits)
  2657 000024BB C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2658 000024BE 01C3                <1> 	add	ebx, eax
  2659                              <1> 	;
  2660 000024C0 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2661 000024C2 A801                <1> 	test	al, 1
  2662 000024C4 740C                <1> 	jz	short spte_0
  2663 000024C6 09D2                <1> 	or	edx, edx
  2664 000024C8 750F                <1> 	jnz	short spte_1
  2665 000024CA 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2666 000024CE 89C2                <1> 	mov	edx, eax
  2667 000024D0 EB09                <1> 	jmp	short spte_2	
  2668                              <1> spte_0:
  2669                              <1> 	; If this PTE contains a swap (disk) address,
  2670                              <1> 	; it can be updated by using 'swap_in' procedure
  2671                              <1> 	; only!
  2672 000024D2 21C0                <1> 	and	eax, eax
  2673 000024D4 7403                <1> 	jz	short spte_1
  2674                              <1> 	; 24/07/2015
  2675                              <1> 	; swapped page ! (on disk)
  2676 000024D6 5B                  <1> 	pop	ebx
  2677                              <1> spte_err:
  2678 000024D7 F9                  <1> 	stc
  2679 000024D8 C3                  <1> 	retn
  2680                              <1> spte_1: 
  2681 000024D9 89D0                <1> 	mov	eax, edx
  2682                              <1> spte_2:
  2683 000024DB 09CA                <1> 	or	edx, ecx
  2684                              <1> 	; 23/06/2015
  2685 000024DD 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2686                              <1> 	; 24/07/2015
  2687 000024DF 5B                  <1> 	pop	ebx
  2688 000024E0 C3                  <1> 	retn
  2689                              <1> 
  2690                              <1> get_pde:	; Get present value of the relevant PDE
  2691                              <1> 	; 20/07/2015
  2692                              <1> 	; 18/04/2015
  2693                              <1> 	; 12/04/2015
  2694                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2695                              <1> 	;
  2696                              <1> 	; INPUT ->
  2697                              <1> 	;	EBX = virtual (linear) address
  2698                              <1> 	;	EAX = page directory (physical) address
  2699                              <1> 	; OUTPUT ->
  2700                              <1> 	;	EDX = Page directory entry address
  2701                              <1> 	;	EAX = Page directory entry value
  2702                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2703                              <1> 	; Modified Registers -> EDX, EAX
  2704                              <1> 	;
  2705 000024E1 89DA                <1> 	mov	edx, ebx
  2706 000024E3 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2707 000024E6 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2708 000024E9 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2709 000024EB 8B02                <1> 	mov	eax, [edx]
  2710 000024ED A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2711 000024EF 751F                <1> 	jnz	short gpte_retn
  2712 000024F1 F9                  <1> 	stc
  2713                              <1> gpde_retn:	
  2714 000024F2 C3                  <1> 	retn
  2715                              <1> 
  2716                              <1> get_pte:
  2717                              <1> 		; Get present value of the relevant PTE
  2718                              <1> 	; 29/07/2015
  2719                              <1> 	; 20/07/2015
  2720                              <1> 	; 18/04/2015
  2721                              <1> 	; 12/04/2015
  2722                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2723                              <1> 	;
  2724                              <1> 	; INPUT ->
  2725                              <1> 	;	EBX = virtual (linear) address
  2726                              <1> 	;	EAX = page directory (physical) address
  2727                              <1> 	; OUTPUT ->
  2728                              <1> 	;	EDX = Page table entry address (if CF=0)
  2729                              <1> 	;	      Page directory entry address (if CF=1)
  2730                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2731                              <1> 	;	EAX = Page table entry value (page address)
  2732                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2733                              <1> 	; Modified Registers -> EAX, EDX
  2734                              <1> 	;
  2735 000024F3 E8E9FFFFFF          <1> 	call 	get_pde
  2736 000024F8 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2737                              <1> 	;jnc	short gpte_1
  2738                              <1> 	;retn
  2739                              <1> ;gpte_1:
  2740 000024FA 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2741 000024FE 89DA                <1> 	mov	edx, ebx
  2742 00002500 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2743 00002503 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2744                              <1> 			 ; clear higher 10 bits (PD bits)
  2745 00002509 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2746 0000250C 01C2                <1> 	add	edx, eax
  2747 0000250E 8B02                <1> 	mov	eax, [edx]
  2748                              <1> gpte_retn:
  2749 00002510 C3                  <1> 	retn
  2750                              <1> 
  2751                              <1> deallocate_page_dir:
  2752                              <1> 	; 15/09/2015
  2753                              <1> 	; 05/08/2015
  2754                              <1> 	; 30/04/2015
  2755                              <1> 	; 28/04/2015
  2756                              <1> 	; 17/10/2014
  2757                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2758                              <1> 	;
  2759                              <1> 	; INPUT ->
  2760                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2761                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2762                              <1> 	; OUTPUT ->
  2763                              <1> 	;	All of page tables in the page directory
  2764                              <1> 	;	and page dir's itself will be deallocated
  2765                              <1> 	;	except 'read only' duplicated pages (will be converted
  2766                              <1> 	;	to writable pages).
  2767                              <1> 	;
  2768                              <1> 	; Modified Registers -> EAX
  2769                              <1> 	;
  2770                              <1> 	;
  2771 00002511 56                  <1> 	push	esi
  2772 00002512 51                  <1> 	push	ecx
  2773 00002513 50                  <1> 	push	eax
  2774 00002514 89C6                <1> 	mov	esi, eax 
  2775 00002516 31C9                <1> 	xor	ecx, ecx
  2776                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2777                              <1> 	; it must not be deallocated
  2778 00002518 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2779                              <1> dapd_0:
  2780 0000251A AD                  <1> 	lodsd
  2781 0000251B A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2782 0000251D 7409                <1> 	jz	short dapd_1	
  2783 0000251F 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2784 00002523 E812000000          <1> 	call	deallocate_page_table			
  2785                              <1> dapd_1:
  2786 00002528 41                  <1> 	inc	ecx ; page directory entry index
  2787 00002529 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2788 0000252F 72E9                <1> 	jb	short dapd_0
  2789                              <1> dapd_2:
  2790 00002531 58                  <1> 	pop	eax
  2791 00002532 E870000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2792 00002537 59                  <1> 	pop	ecx
  2793 00002538 5E                  <1> 	pop	esi
  2794 00002539 C3                  <1> 	retn
  2795                              <1> 
  2796                              <1> deallocate_page_table:
  2797                              <1> 	; 17/07/2022
  2798                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2799                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2800                              <1> 	; 19/09/2015
  2801                              <1> 	; 15/09/2015
  2802                              <1> 	; 05/08/2015
  2803                              <1> 	; 30/04/2015
  2804                              <1> 	; 28/04/2015
  2805                              <1> 	; 24/10/2014
  2806                              <1> 	; 23/10/2014
  2807                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2808                              <1> 	;
  2809                              <1> 	; INPUT ->
  2810                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2811                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2812                              <1> 	;	(ECX = page directory entry index)
  2813                              <1> 	; OUTPUT ->
  2814                              <1> 	;	All of pages in the page table and page table's itself
  2815                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2816                              <1> 	;	(will be converted to writable pages).
  2817                              <1> 	;
  2818                              <1> 	; Modified Registers -> EAX
  2819                              <1> 	;
  2820 0000253A 56                  <1> 	push	esi
  2821 0000253B 57                  <1> 	push	edi
  2822 0000253C 52                  <1> 	push	edx
  2823 0000253D 50                  <1> 	push	eax ; *
  2824 0000253E 89C6                <1> 	mov	esi, eax 
  2825 00002540 31FF                <1> 	xor	edi, edi ; 0
  2826                              <1> dapt_0:
  2827 00002542 AD                  <1> 	lodsd
  2828 00002543 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2829 00002545 7453                <1> 	jz	short dapt_1
  2830                              <1> 	;
  2831 00002547 A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2832                              <1> 				  ; (must be 1)
  2833 00002549 753D                <1> 	jnz	short dapt_3
  2834                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2835 0000254B 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2836                              <1> 				   ; as child's page ?
  2837 0000254F 7442                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2838                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2839                              <1> 	; ECX = page directory entry index (0-1023)
  2840 00002551 53                  <1> 	push	ebx
  2841 00002552 51                  <1> 	push	ecx
  2842                              <1> 	;shl	cx, 2 ; *4 
  2843                              <1> 	; 17/07/2022
  2844 00002553 C1E102              <1> 	shl	ecx, 2
  2845 00002556 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2846 00002558 8B0B                <1> 	mov	ecx, [ebx]
  2847 0000255A F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2848 0000255D 7427                <1> 	jz	short dapt_2	; parent process does not use this page
  2849 0000255F 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2850                              <1> 	; EDI = page table entry index (0-1023)
  2851 00002564 89FA                <1> 	mov	edx, edi 
  2852                              <1> 	;shl	dx, 2 ; *4
  2853                              <1> 	; 17/07/2022
  2854 00002566 C1E202              <1> 	shl	edx, 2
  2855 00002569 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2856 0000256B 8B1A                <1> 	mov	ebx, [edx]
  2857 0000256D F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2858 00002570 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2859 00002572 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2860 00002576 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2861 0000257B 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2862 0000257D 7507                <1> 	jne	short dapt_2	; not same page
  2863                              <1> 				; deallocate the child's page
  2864 0000257F 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2865 00002582 59                  <1> 	pop	ecx
  2866 00002583 5B                  <1> 	pop	ebx
  2867 00002584 EB0D                <1> 	jmp	short dapt_4
  2868                              <1> 
  2869                              <1> ; 24/12/2021
  2870                              <1> ; ('dapt_1' is disabled)
  2871                              <1> ;
  2872                              <1> ;dapt_1:
  2873                              <1> ;	or	eax, eax	; swapped page ?
  2874                              <1> ;	jz	short dapt_5	; no
  2875                              <1> ;				; yes
  2876                              <1> ;	shr	eax, 1
  2877                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2878                              <1> ;				  ; on the swap disk (or in file)
  2879                              <1> ;	jmp	short dapt_5
  2880                              <1> dapt_2:
  2881 00002586 59                  <1> 	pop	ecx
  2882 00002587 5B                  <1> 	pop	ebx
  2883                              <1> dapt_3:	
  2884                              <1> 	; 12/07/2016
  2885 00002588 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2886 0000258C 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2887                              <1> 	;
  2888                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2889 0000258E E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2890                              <1> dapt_4:
  2891 00002593 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2892                              <1> dapt_1:	; 24/12/2021
  2893                              <1> dapt_5:
  2894 0000259A 47                  <1> 	inc	edi ; page table entry index
  2895 0000259B 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2896 000025A1 729F                <1> 	jb	short dapt_0
  2897                              <1> 	;
  2898 000025A3 58                  <1> 	pop	eax ; *
  2899 000025A4 5A                  <1> 	pop	edx
  2900 000025A5 5F                  <1> 	pop	edi	
  2901 000025A6 5E                  <1> 	pop	esi
  2902                              <1> 	;
  2903                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2904                              <1> 	;retn
  2905                              <1> 
  2906                              <1> deallocate_page:
  2907                              <1> 	; 15/09/2015
  2908                              <1> 	; 28/04/2015
  2909                              <1> 	; 10/03/2015
  2910                              <1> 	; 17/10/2014
  2911                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2912                              <1> 	;
  2913                              <1> 	; INPUT -> 
  2914                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2915                              <1> 	; OUTPUT ->
  2916                              <1> 	;	[free_pages] is increased
  2917                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2918                              <1> 	;	CF = 1 if the page is already deallocated
  2919                              <1> 	; 	       (or not allocated) before.  
  2920                              <1> 	;
  2921                              <1> 	; Modified Registers -> EAX
  2922                              <1> 	;
  2923 000025A7 53                  <1> 	push	ebx
  2924 000025A8 52                  <1> 	push	edx
  2925                              <1> 	;
  2926 000025A9 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2927                              <1> 				     ; 12 bits right
  2928                              <1> 				     ; to get page number
  2929 000025AC 89C2                <1> 	mov	edx, eax
  2930                              <1> 	; 15/09/2015
  2931 000025AE C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2932                              <1> 				     ; (1 allocation bit = 1 page)
  2933                              <1> 				     ; (1 allocation bytes = 8 pages)
  2934 000025B1 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2935                              <1> 				     ; (to get 32 bit position)			
  2936                              <1> 	;
  2937 000025B4 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2938 000025B9 01D3                <1> 	add	ebx, edx
  2939 000025BB 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2940                              <1> 				     ; (allocation bit position)	 
  2941 000025BE 3B15[44610000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2942                              <1> 				     ; than the address in 'next_page' ?
  2943                              <1> 				     ; (next/first free page value)		
  2944 000025C4 7306                <1> 	jnb	short dap_1	     ; no	
  2945 000025C6 8915[44610000]      <1> 	mov	[next_page], edx     ; yes
  2946                              <1> dap_1:
  2947 000025CC 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2948                              <1> 				     ; set relevant bit to 1.
  2949                              <1> 				     ; set CF to the previous bit value	
  2950                              <1> 	;cmc			     ; complement carry flag	
  2951                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2952                              <1> 				     ; if the page is already deallocated
  2953                              <1> 				     ; before.	
  2954 000025CF FF05[40610000]      <1>         inc     dword [free_pages]
  2955                              <1> dap_2:
  2956 000025D5 5A                  <1> 	pop	edx
  2957 000025D6 5B                  <1> 	pop	ebx
  2958 000025D7 C3                  <1> 	retn
  2959                              <1> 
  2960                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2961                              <1> ;;                                                              ;;
  2962                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2963                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2964                              <1> ;;                                                              ;;
  2965                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2966                              <1> 
  2967                              <1> ;;$Revision: 5057 $
  2968                              <1> 
  2969                              <1> 
  2970                              <1> ;;align 4
  2971                              <1> ;;proc alloc_page
  2972                              <1> 
  2973                              <1> ;;        pushfd
  2974                              <1> ;;        cli
  2975                              <1> ;;        push    ebx
  2976                              <1> ;;;//-
  2977                              <1> ;;        cmp     [pg_data.pages_free], 1
  2978                              <1> ;;        jle     .out_of_memory
  2979                              <1> ;;;//-
  2980                              <1> ;;
  2981                              <1> ;;        mov     ebx, [page_start]
  2982                              <1> ;;        mov     ecx, [page_end]
  2983                              <1> ;;.l1:
  2984                              <1> ;;        bsf     eax, [ebx];
  2985                              <1> ;;        jnz     .found
  2986                              <1> ;;        add     ebx, 4
  2987                              <1> ;;        cmp     ebx, ecx
  2988                              <1> ;;        jb      .l1
  2989                              <1> ;;        pop     ebx
  2990                              <1> ;;        popfd
  2991                              <1> ;;        xor     eax, eax
  2992                              <1> ;;        ret
  2993                              <1> ;;.found:
  2994                              <1> ;;;//-
  2995                              <1> ;;        dec     [pg_data.pages_free]
  2996                              <1> ;;        jz      .out_of_memory
  2997                              <1> ;;;//-
  2998                              <1> ;;        btr     [ebx], eax
  2999                              <1> ;;        mov     [page_start], ebx
  3000                              <1> ;;        sub     ebx, sys_pgmap
  3001                              <1> ;;        lea     eax, [eax+ebx*8]
  3002                              <1> ;;        shl     eax, 12
  3003                              <1> ;;;//-       dec [pg_data.pages_free]
  3004                              <1> ;;        pop     ebx
  3005                              <1> ;;        popfd
  3006                              <1> ;;        ret
  3007                              <1> ;;;//-
  3008                              <1> ;;.out_of_memory:
  3009                              <1> ;;        mov     [pg_data.pages_free], 1
  3010                              <1> ;;        xor     eax, eax
  3011                              <1> ;;        pop     ebx
  3012                              <1> ;;        popfd
  3013                              <1> ;;        ret
  3014                              <1> ;;;//-
  3015                              <1> ;;endp
  3016                              <1> 
  3017                              <1> duplicate_page_dir:
  3018                              <1> 	; 21/09/2015
  3019                              <1> 	; 31/08/2015
  3020                              <1> 	; 20/07/2015
  3021                              <1> 	; 28/04/2015
  3022                              <1> 	; 27/04/2015
  3023                              <1> 	; 18/04/2015
  3024                              <1> 	; 12/04/2015
  3025                              <1> 	; 18/10/2014
  3026                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3027                              <1> 	;
  3028                              <1> 	; INPUT -> 
  3029                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3030                              <1> 	;		    page directory.
  3031                              <1> 	; OUTPUT ->
  3032                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3033                              <1> 	;	       page directory.
  3034                              <1> 	;	(New page directory with new page table entries.)
  3035                              <1> 	;	(New page tables with read only copies of the parent's
  3036                              <1> 	;	pages.)
  3037                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3038                              <1> 	;
  3039                              <1> 	; Modified Registers -> none (except EAX)
  3040                              <1> 	;
  3041 000025D8 E804FEFFFF          <1> 	call	allocate_page
  3042 000025DD 723E                <1> 	jc	short dpd_err
  3043                              <1> 	;
  3044 000025DF 55                  <1> 	push	ebp ; 20/07/2015
  3045 000025E0 56                  <1> 	push	esi
  3046 000025E1 57                  <1> 	push	edi
  3047 000025E2 53                  <1> 	push	ebx
  3048 000025E3 51                  <1> 	push	ecx
  3049 000025E4 8B35[53650000]      <1> 	mov	esi, [u.pgdir]
  3050 000025EA 89C7                <1> 	mov	edi, eax
  3051 000025EC 50                  <1> 	push	eax ; save child's page directory address
  3052                              <1> 	; 31/08/2015
  3053                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3054                              <1> 	; (use same system space for all user page tables) 
  3055 000025ED A5                  <1> 	movsd
  3056 000025EE BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3057 000025F3 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3058                              <1> dpd_0:	
  3059 000025F8 AD                  <1> 	lodsd
  3060                              <1> 	;or	eax, eax
  3061                              <1>         ;jnz     short dpd_1
  3062 000025F9 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3063 000025FB 7508                <1> 	jnz	short dpd_1
  3064                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3065 000025FD 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3066 00002603 EB0F                <1> 	jmp	short dpd_2
  3067                              <1> dpd_1:	
  3068 00002605 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3069 00002609 89C3                <1> 	mov	ebx, eax
  3070                              <1> 	; EBX = Parent's page table address
  3071 0000260B E81F000000          <1> 	call	duplicate_page_table
  3072 00002610 720C                <1> 	jc	short dpd_p_err
  3073                              <1> 	; EAX = Child's page table address
  3074 00002612 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3075                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3076                              <1> 			 ; (present, writable, user)
  3077                              <1> dpd_2:
  3078 00002614 AB                  <1> 	stosd
  3079 00002615 E2E1                <1> 	loop	dpd_0
  3080                              <1> 	;
  3081 00002617 58                  <1> 	pop	eax  ; restore child's page directory address
  3082                              <1> dpd_3:
  3083 00002618 59                  <1> 	pop	ecx
  3084 00002619 5B                  <1> 	pop	ebx
  3085 0000261A 5F                  <1> 	pop	edi
  3086 0000261B 5E                  <1> 	pop	esi
  3087 0000261C 5D                  <1> 	pop	ebp ; 20/07/2015
  3088                              <1> dpd_err:
  3089 0000261D C3                  <1> 	retn
  3090                              <1> dpd_p_err:
  3091                              <1> 	; release the allocated pages missing (recover free space)
  3092 0000261E 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3093 0000261F 8B1D[53650000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3094 00002625 E8E7FEFFFF          <1> 	call 	deallocate_page_dir
  3095 0000262A 29C0                <1> 	sub	eax, eax ; 0
  3096 0000262C F9                  <1> 	stc
  3097 0000262D EBE9                <1> 	jmp	short dpd_3	
  3098                              <1> 
  3099                              <1> duplicate_page_table:
  3100                              <1> 	; 31/12/2021
  3101                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3102                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3103                              <1> 	; 21/09/2015
  3104                              <1> 	; 20/07/2015
  3105                              <1> 	; 05/05/2015
  3106                              <1> 	; 28/04/2015
  3107                              <1> 	; 27/04/2015
  3108                              <1> 	; 18/04/2015
  3109                              <1> 	; 18/10/2014
  3110                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3111                              <1> 	;
  3112                              <1> 	; INPUT -> 
  3113                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3114                              <1> 	;       20/02/2017		 
  3115                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3116                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3117                              <1> 	; OUTPUT ->
  3118                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3119                              <1> 	;	      (with 'read only' attribute of page table entries)
  3120                              <1> 	;	20/02/2017
  3121                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3122                              <1> 	;	
  3123                              <1> 	;	CF = 1 -> error 
  3124                              <1> 	;
  3125                              <1> 	; Modified Registers -> EBP (except EAX)
  3126                              <1> 	;
  3127 0000262F E8ADFDFFFF          <1> 	call	allocate_page
  3128 00002634 725B                <1> 	jc	short dpt_err
  3129                              <1> 	;
  3130 00002636 50                  <1> 	push	eax ; *
  3131 00002637 56                  <1> 	push	esi
  3132 00002638 57                  <1> 	push	edi
  3133 00002639 52                  <1> 	push	edx
  3134 0000263A 51                  <1> 	push	ecx
  3135                              <1> 	;
  3136 0000263B 89DE                <1> 	mov	esi, ebx
  3137 0000263D 89C7                <1> 	mov	edi, eax
  3138 0000263F 89C2                <1> 	mov	edx, eax
  3139 00002641 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3140                              <1> dpt_0:
  3141 00002647 AD                  <1> 	lodsd
  3142 00002648 21C0                <1> 	and	eax, eax
  3143 0000264A 7435                <1> 	jz	short dpt_3
  3144 0000264C A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3145                              <1> 	; 24/12/2021
  3146 0000264E 7503                <1> 	jnz	short dpt_1
  3147                              <1> 	;jz	short dpt_p_err
  3148                              <1> 	; 31/12/2021
  3149 00002650 F9                  <1> 	stc
  3150 00002651 EB39                <1> 	jmp	short dpt_p_err
  3151                              <1> 
  3152                              <1> ; 24/12/2021
  3153                              <1> ; ('reload_page' procedure call is disabled)
  3154                              <1> ;
  3155                              <1> ;	; 20/07/2015
  3156                              <1> ;	; ebp = virtual (linear) address of the memory page
  3157                              <1> ;	call	reload_page ; 28/04/2015
  3158                              <1> ;	jc	short dpt_p_err
  3159                              <1> dpt_1:
  3160                              <1> 	; 21/09/2015
  3161 00002653 89C1                <1> 	mov	ecx, eax
  3162 00002655 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3163 00002659 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3164 0000265C 751A                <1> 	jnz	short dpt_2
  3165                              <1> 	; Read only (parent) page
  3166                              <1> 	; 	- there is a third process which uses this page -
  3167                              <1> 	; Allocate a new page for the child process
  3168 0000265E E87EFDFFFF          <1> 	call	allocate_page
  3169 00002663 7227                <1> 	jc	short dpt_p_err
  3170 00002665 57                  <1> 	push	edi
  3171 00002666 56                  <1> 	push	esi
  3172 00002667 89CE                <1> 	mov	esi, ecx
  3173 00002669 89C7                <1> 	mov	edi, eax
  3174 0000266B B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3175 00002670 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3176 00002672 5E                  <1> 	pop	esi
  3177 00002673 5F                  <1> 	pop	edi
  3178                              <1> 	;
  3179                              <1> 
  3180                              <1> ; 24/12/2021
  3181                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3182                              <1> ; 
  3183                              <1> ;	push	ebx
  3184                              <1> ;	push	eax
  3185                              <1> ;	; 20/07/2015
  3186                              <1> ;	mov	ebx, ebp
  3187                              <1> ;	; ebx = virtual (linear) address of the memory page
  3188                              <1> ;	call	add_to_swap_queue
  3189                              <1> ;	pop	eax
  3190                              <1> ;	pop	ebx
  3191                              <1> 
  3192                              <1> 	; 21/09/2015
  3193 00002674 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3194                              <1> 		; user + writable + present page
  3195 00002676 EB09                <1> 	jmp	short dpt_3
  3196                              <1> dpt_2:
  3197                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3198 00002678 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3199                              <1> 		    ; (read only page!)
  3200 0000267A 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3201 0000267D 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3202                              <1> dpt_3:
  3203 00002681 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3204                              <1> 	;
  3205 00002682 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3206                              <1> 	;
  3207 00002688 39D7                <1> 	cmp	edi, edx
  3208 0000268A 72BB                <1> 	jb	short dpt_0
  3209                              <1> dpt_p_err:
  3210 0000268C 59                  <1> 	pop	ecx
  3211 0000268D 5A                  <1> 	pop	edx
  3212 0000268E 5F                  <1> 	pop	edi
  3213 0000268F 5E                  <1> 	pop	esi
  3214 00002690 58                  <1> 	pop	eax ; *
  3215                              <1> dpt_err:
  3216 00002691 C3                  <1> 	retn
  3217                              <1> 
  3218                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3219                              <1> 	; 31/12/2021
  3220                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3221                              <1> 	; 21/09/2015
  3222                              <1> 	; 19/09/2015
  3223                              <1> 	; 17/09/2015
  3224                              <1> 	; 28/08/2015
  3225                              <1> 	; 20/07/2015
  3226                              <1> 	; 28/06/2015
  3227                              <1> 	; 03/05/2015
  3228                              <1> 	; 30/04/2015
  3229                              <1> 	; 18/04/2015
  3230                              <1> 	; 12/04/2015
  3231                              <1> 	; 30/10/2014
  3232                              <1> 	; 11/09/2014
  3233                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3234                              <1> 	;
  3235                              <1> 	; Note: This is not an interrupt/exception handler.
  3236                              <1> 	;	This is a 'page fault remedy' subroutine 
  3237                              <1> 	;	which will be called by standard/uniform
  3238                              <1> 	;	exception handler.
  3239                              <1> 	;
  3240                              <1> 	; INPUT -> 
  3241                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3242                              <1> 	;
  3243                              <1> 	;	cr2 = the virtual (linear) address 
  3244                              <1> 	;	      which has caused to page fault (19/09/2015)
  3245                              <1> 	;
  3246                              <1> 	; OUTPUT ->
  3247                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3248                              <1> 	;	EAX = 0 -> no error
  3249                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3250                              <1> 	;
  3251                              <1> 	; Modified Registers -> none (except EAX)
  3252                              <1> 	;	
  3253                              <1>         ;
  3254                              <1>         ; ERROR CODE:
  3255                              <1> 	;	 31  .....	4   3	2   1	0
  3256                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3257                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3258                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3259                              <1> 	;
  3260                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3261                              <1>     	;		a page-protection violation. When not set,
  3262                              <1> 	;		it was caused by a non-present page.
  3263                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3264                              <1> 	;		a page write. When not set, it was caused
  3265                              <1> 	;		by a page read.
  3266                              <1> 	; U : USER    -	When set, the page fault was caused 
  3267                              <1> 	;		while CPL = 3. 
  3268                              <1> 	;		This does not necessarily mean that
  3269                              <1> 	;		the page fault was a privilege violation.
  3270                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3271                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3272                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3273                              <1> 	;     FETCH	an instruction fetch
  3274                              <1> 	;
  3275                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3276                              <1> 	;  31               22                  12 11                    0
  3277                              <1> 	; +-------------------+-------------------+-----------------------+
  3278                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3279                              <1>        	; +-------------------+-------------------+-----------------------+
  3280                              <1> 	;
  3281                              <1> 
  3282                              <1> 	;; CR3 REGISTER (Control Register 3)
  3283                              <1> 	;  31                                   12             5 4 3 2   0
  3284                              <1> 	; +---------------------------------------+-------------+---+-----+
  3285                              <1>       	; |                                       |  		|P|P|     |
  3286                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3287                              <1>       	; |                                       | 		|D|T|     |
  3288                              <1>    	; +---------------------------------------+-------------+---+-----+
  3289                              <1> 	;
  3290                              <1> 	;	PWT    - WRITE THROUGH
  3291                              <1> 	;	PCD    - CACHE DISABLE		
  3292                              <1> 	;
  3293                              <1> 	;
  3294                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3295                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3296                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3297                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3298                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3299                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3300                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3301                              <1> 	;
  3302                              <1>         ;       P      - PRESENT
  3303                              <1>         ;       R/W    - READ/WRITE
  3304                              <1>         ;       U/S    - USER/SUPERVISOR
  3305                              <1> 	;	PWT    - WRITE THROUGH
  3306                              <1> 	;	PCD    - CACHE DISABLE	
  3307                              <1> 	;	A      - ACCESSED	
  3308                              <1>         ;       D      - DIRTY (IGNORED)
  3309                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3310                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3311                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3312                              <1> 	;
  3313                              <1> 	;
  3314                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3315                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3316                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3317                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3318                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3319                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3320                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3321                              <1> 	;
  3322                              <1>         ;       P      - PRESENT
  3323                              <1>         ;       R/W    - READ/WRITE
  3324                              <1>         ;       U/S    - USER/SUPERVISOR
  3325                              <1> 	;	PWT    - WRITE THROUGH
  3326                              <1> 	;	PCD    - CACHE DISABLE	
  3327                              <1> 	;	A      - ACCESSED	
  3328                              <1>         ;       D      - DIRTY
  3329                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3330                              <1> 	;	G      - GLOBAL	 
  3331                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3332                              <1> 	;
  3333                              <1> 	;
  3334                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3335                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3336                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3337                              <1>       	; |                                       |     | | | | | | |U|R| |
  3338                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3339                              <1>       	; |                                       |     | | | | | | |S|W| |
  3340                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3341                              <1> 	;
  3342                              <1>         ;       P      - PRESENT
  3343                              <1>         ;       R/W    - READ/WRITE
  3344                              <1>         ;       U/S    - USER/SUPERVISOR
  3345                              <1>         ;       D      - DIRTY
  3346                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3347                              <1> 	;
  3348                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3349                              <1> 	;
  3350                              <1> 	;
  3351                              <1> 	;; Invalid Page Table Entry
  3352                              <1> 	; 31                                                           1 0
  3353                              <1>       	; +-------------------------------------------------------------+-+
  3354                              <1>       	; |                                                             | |
  3355                              <1>       	; |                          AVAILABLE                          |0|
  3356                              <1>       	; |                                                             | |
  3357                              <1>       	; +-------------------------------------------------------------+-+
  3358                              <1> 	;
  3359                              <1> 
  3360 00002692 53                  <1> 	push	ebx
  3361 00002693 52                  <1> 	push	edx
  3362 00002694 51                  <1> 	push	ecx
  3363                              <1> 	;
  3364                              <1> 	; 21/09/2015 (debugging)
  3365 00002695 FF05[63650000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3366 0000269B FF05[EC610000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3367                              <1> 	; 28/06/2015
  3368                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3369 000026A1 8A15[E4610000]      <1> 	mov	dl, [error_code]
  3370                              <1> 	;
  3371 000026A7 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3372                              <1> 			; sign
  3373 000026AA 7425                <1> 	jz	short pfh_alloc_np
  3374                              <1> 	; 
  3375                              <1> 	; If it is not a 'write on read only page' type page fault
  3376                              <1> 	; major page fault error with minor reason must be returned without 
  3377                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3378                              <1> 	; after return here!
  3379                              <1> 	; Page fault will be remedied, by copying page contents
  3380                              <1> 	; to newly allocated page with write permission;
  3381                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3382                              <1> 	; used for working with minimum possible memory usage. 
  3383                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3384                              <1> 	; process with 'read only' flag. If the child process attempts to
  3385                              <1> 	; write on these read only pages, page fault will be directed here
  3386                              <1> 	; for allocating a new page with same data/content. 
  3387                              <1> 	;
  3388                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3389                              <1> 	; will not force to separate CODE and DATA space 
  3390                              <1> 	; in a process/program... 
  3391                              <1> 	; CODE segment/section may contain DATA!
  3392                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3393                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3394                              <1> 	;	
  3395 000026AC F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3396                              <1> 			; sign
  3397 000026AF 7418                <1>         jz      pfh_p_err
  3398                              <1> 	; 31/08/2015
  3399 000026B1 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3400                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3401 000026B4 7413                <1>         jz	short pfh_pv_err
  3402                              <1> 	;
  3403                              <1> 	; make a new page and copy the parent's page content
  3404                              <1> 	; as the child's new page content
  3405                              <1> 	;
  3406 000026B6 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3407                              <1> 			 ; which has caused to page fault
  3408 000026B9 E87C000000          <1> 	call 	copy_page
  3409 000026BE 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3410                              <1> 	;
  3411 000026C0 EB72                <1>         jmp     pfh_cpp_ok
  3412                              <1> 
  3413                              <1> 	; 31/12/2021 (short jump)
  3414                              <1> pfh_im_err:
  3415 000026C2 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3416                              <1> 			; Major (Primary) Error: Page Fault
  3417                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3418 000026C7 EB6D                <1> 	jmp	short pfh_err_retn
  3419                              <1> 
  3420                              <1> 	; 31/12/2021
  3421                              <1> pfh_p_err: ; 09/03/2015
  3422                              <1> pfh_pv_err:
  3423                              <1> 	; Page fault was caused by a protection-violation
  3424 000026C9 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3425                              <1> 			; Major (Primary) Error: Page Fault
  3426                              <1> 			; Minor (Secondary) Error: Protection violation !
  3427 000026CE F9                  <1> 	stc
  3428 000026CF EB65                <1> 	jmp	short pfh_err_retn
  3429                              <1> 	
  3430                              <1> pfh_alloc_np:
  3431 000026D1 E80BFDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3432 000026D6 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3433                              <1> pfh_chk_cpl:
  3434                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3435                              <1> 		; (Lower 12 bits are ZERO, because 
  3436                              <1> 		;	the address is on a page boundary)
  3437 000026D8 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3438 000026DB 7505                <1> 	jnz	short pfh_um
  3439                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3440 000026DD 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3441                              <1> 			 ; of the current/active page directory
  3442                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3443                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3444 000026E0 EB06                <1> 	jmp	short pfh_get_pde
  3445                              <1> 	;
  3446                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3447 000026E2 8B1D[53650000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3448                              <1> 			; Physical address of the USER's page directory
  3449                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3450                              <1> pfh_get_pde:
  3451 000026E8 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3452 000026EB 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3453                              <1> 			 ; which has been caused to page fault
  3454                              <1> 			 ;
  3455 000026EE C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3456 000026F1 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3457                              <1> 	;
  3458 000026F4 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3459 000026F6 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3460 000026F8 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3461 000026FB 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3462                              <1> 			  	  ; set/validate page directory entry
  3463 000026FD 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3464 00002702 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3465 00002704 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3466 00002706 EB16                <1> 	jmp	short pfh_get_pte
  3467                              <1> pfh_set_pde:
  3468                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3469                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3470                              <1> 	;
  3471 00002708 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3472 0000270A 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3473 0000270C 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3474 0000270E 89C3                <1> 	mov	ebx, eax
  3475 00002710 E8CCFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3476 00002715 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3477                              <1> pfh_spde_1:
  3478                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3479 00002717 89C1                <1> 	mov	ecx, eax
  3480 00002719 E834FDFFFF          <1> 	call	clear_page ; Clear page content
  3481                              <1> pfh_get_pte:
  3482 0000271E 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3483                              <1> 			 ; which has been caused to page fault
  3484 00002721 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3485 00002723 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3486                              <1> 			 ; higher 20 bits of the page fault address 
  3487 00002726 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3488 0000272B C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3489 0000272E 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3490                              <1> ; 24/12/2021
  3491                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3492                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3493                              <1> ; 24/12/2021
  3494                              <1> ; ('swap_in' procedure call has been disabled)
  3495                              <1> ;
  3496                              <1> ;	and	eax, eax
  3497                              <1> ;	jz	short pfh_gpte_1
  3498                              <1> ;	; 20/07/2015
  3499                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3500                              <1> ;	push	ebp ; 20/07/2015
  3501                              <1> ;	mov	ebp, cr2
  3502                              <1> ;		; ECX = physical address of the page table entry
  3503                              <1> ;		; EBX = Memory page address (physical!)
  3504                              <1> ;		; EAX = Swap disk (offset) address
  3505                              <1> ;		; EBP = virtual address (page fault address)
  3506                              <1> ;	call	swap_in
  3507                              <1> ;	pop	ebp
  3508                              <1> ;	jc      short pfh_err_retn
  3509                              <1> ;	xchg	ecx, ebx
  3510                              <1> ;		; EBX = physical address of the page table entry
  3511                              <1> ;		; ECX = new page
  3512                              <1> pfh_gpte_1:
  3513 00002730 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3514 00002732 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3515                              <1> pfh_cpp_ok:
  3516                              <1> ; 24/12/2021
  3517                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3518                              <1> ;
  3519                              <1> ;	; 20/07/2015
  3520                              <1> ;	mov	ebx, cr2
  3521                              <1> ;	call 	add_to_swap_queue
  3522                              <1> 	;
  3523                              <1> 	; The new PTE (which contains the new page) will be added to 
  3524                              <1> 	; the swap queue, here. 
  3525                              <1> 	; (Later, if memory will become insufficient, 
  3526                              <1> 	; one page will be swapped out which is at the head of 
  3527                              <1> 	; the swap queue by using FIFO and access check methods.)
  3528                              <1> 	;
  3529 00002734 31C0                <1> 	xor	eax, eax  ; 0
  3530                              <1> 	;
  3531                              <1> pfh_err_retn:
  3532 00002736 59                  <1> 	pop	ecx
  3533 00002737 5A                  <1> 	pop	edx
  3534 00002738 5B                  <1> 	pop	ebx
  3535 00002739 C3                  <1> 	retn 
  3536                              <1> 	
  3537                              <1> copy_page:
  3538                              <1> 	; 17/07/2022
  3539                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3540                              <1> 	; 16/04/2021
  3541                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3542                              <1> 	; 22/09/2015
  3543                              <1> 	; 21/09/2015
  3544                              <1> 	; 19/09/2015
  3545                              <1> 	; 07/09/2015
  3546                              <1> 	; 31/08/2015
  3547                              <1> 	; 20/07/2015
  3548                              <1> 	; 05/05/2015
  3549                              <1> 	; 03/05/2015
  3550                              <1> 	; 18/04/2015
  3551                              <1> 	; 12/04/2015
  3552                              <1> 	; 30/10/2014
  3553                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3554                              <1> 	;
  3555                              <1> 	; INPUT -> 
  3556                              <1> 	;	EBX = Virtual (linear) address of source page
  3557                              <1> 	;	     (Page fault address)
  3558                              <1> 	; OUTPUT ->
  3559                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3560                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3561                              <1> 	;	EAX = 0 (CF = 1) 
  3562                              <1> 	;		if there is not a free page to be allocated
  3563                              <1> 	;	(page content of the source page will be copied
  3564                              <1> 	;	onto the target/new page) 	
  3565                              <1> 	;
  3566                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3567                              <1> 	;
  3568                              <1> 
  3569                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3570                              <1> 	; INPUT: 
  3571                              <1> 	;	EBX = Virtual (linear) address of source page
  3572                              <1> 	;	     (Page fault address)
  3573                              <1> 	; OUTPUT:
  3574                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3575                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3576                              <1> 	;	EAX = 0 (CF = 1) 
  3577                              <1> 	;		if there is not a free page to be allocated
  3578                              <1> 	;	(page content of the source page will be copied
  3579                              <1> 	;	onto the target/new page) 	
  3580                              <1> 	;
  3581                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3582                              <1> 	
  3583 0000273A 56                  <1> 	push	esi ; *
  3584 0000273B 57                  <1> 	push	edi ; **
  3585                              <1> 	; 16/04/2021
  3586                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3587                              <1> 	;push	ebx ; ***
  3588                              <1> 	;push	ecx ; ****
  3589 0000273C 31F6                <1> 	xor 	esi, esi
  3590 0000273E C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3591 00002741 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3592 00002743 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3593 00002746 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3594 00002749 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3595 0000274B 031D[53650000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3596 00002751 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3597 00002753 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3598 00002757 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3599 00002759 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3600                              <1> 	;shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3601                              <1> 	; 17/07/2022
  3602 0000275F C1E302              <1> 	shl	ebx, 2
  3603 00002762 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3604                              <1> 	; 07/09/2015
  3605 00002764 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3606                              <1> 				     ; read only page as a child process?)	
  3607 00002769 7509                <1> 	jnz	short cpp_0 ; yes
  3608 0000276B 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3609 0000276D 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3610 00002772 EB31                <1> 	jmp	short cpp_1
  3611                              <1> cpp_0:
  3612 00002774 89FE                <1> 	mov	esi, edi
  3613 00002776 0335[57650000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3614 0000277C 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3615 0000277E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3616 00002782 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3617 00002784 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3618                              <1> 	;shl	si, 2	   ; shift 2 bits left to get PTE offset
  3619                              <1> 	; 17/07/2022
  3620 0000278A C1E602              <1> 	shl	esi, 2
  3621 0000278D 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3622 0000278F 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3623                              <1> 	; 21/09/2015
  3624 00002791 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3625 00002793 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3626                              <1> 	;
  3627 00002797 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3628 0000279A 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3629                              <1> 	;
  3630 0000279C 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3631 000027A1 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3632 000027A3 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3633                              <1> 			    ; Convert child's page to writable page
  3634                              <1> cpp_1:
  3635 000027A5 E837FCFFFF          <1> 	call	allocate_page
  3636 000027AA 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3637 000027AC 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3638 000027AE 7405                <1> 	jz	short cpp_2
  3639                              <1> 		; Convert read only page to writable page 
  3640                              <1> 		;(for the parent of the current process)
  3641                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3642                              <1> 	; 22/09/2015
  3643 000027B0 890E                <1> 	mov	[esi], ecx
  3644 000027B2 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3645                              <1> 				 ; 1+2+4 = 7
  3646                              <1> cpp_2:
  3647 000027B5 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3648                              <1> 	; 07/09/2015
  3649 000027B7 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3650 000027B9 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3651 000027BE F3A5                <1> 	rep	movsd ; 31/08/2015
  3652                              <1> cpp_3:		
  3653 000027C0 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3654 000027C2 8903                <1> 	mov	[ebx], eax ; Update PTE
  3655 000027C4 28C0                <1> 	sub	al, al ; clear attributes
  3656                              <1> cpp_4:
  3657                              <1> 	; 16/04/2021
  3658                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3659                              <1> 	;pop	ecx ; ****
  3660                              <1> 	;pop	ebx ; ***
  3661 000027C6 5F                  <1> 	pop	edi ; **
  3662 000027C7 5E                  <1> 	pop	esi ; *
  3663 000027C8 C3                  <1> 	retn
  3664                              <1> 
  3665                              <1> ;; 28/04/2015
  3666                              <1> ;; 24/10/2014
  3667                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3668                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3669                              <1> ;;
  3670                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3671                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3672                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3673                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3674                              <1> ;;
  3675                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3676                              <1> ;;
  3677                              <1> ;; Method:
  3678                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3679                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3680                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3681                              <1> ;;	When a new page is being allocated, swap queue is updated
  3682                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3683                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3684                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3685                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3686                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3687                              <1> ;;	offset value becomes it's previous offset value - 4.
  3688                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3689                              <1> ;;	the queue/list is not shifted.
  3690                              <1> ;;	After the queue/list shift, newly allocated page is added
  3691                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3692                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3693                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3694                              <1> ;;	
  3695                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3696                              <1> ;;	the first non-accessed, writable page in the list, 
  3697                              <1> ;;	from the head to the tail. The list is shifted to left 
  3698                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3699                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3700                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3701                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3702                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3703                              <1> ;;	procedure will be failed)...
  3704                              <1> ;;
  3705                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3706                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3707                              <1> ;;	(PTE) will be added to the tail of the queue after
  3708                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3709                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3710                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3711                              <1> ;;
  3712                              <1> ;;
  3713                              <1> ;;	
  3714                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3715                              <1> ;;
  3716                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3717                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3718                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3719                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3720                              <1> ;;
  3721                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3722                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3723                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3724                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3725                              <1> ;; 		 (entire swap space must be accessed by using
  3726                              <1> ;;		 31 bit offset address) 
  3727                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3728                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3729                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3730                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3731                              <1> ;;
  3732                              <1> ;; 					
  3733                              <1> ;; Method:
  3734                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3735                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3736                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3737                              <1> ;;	Swapping out is performed by using swap page queue.
  3738                              <1> ;;
  3739                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3740                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3741                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3742                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3743                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3744                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3745                              <1> ;;	calculated by adding offset value to the swap partition's 
  3746                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3747                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3748                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3749                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3750                              <1> ;;	is in a partitioned virtual hard disk.) 
  3751                              <1> ;;
  3752                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3753                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3754                              <1> ;;
  3755                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3756                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3757                              <1> ;;
  3758                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3759                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3760                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3761                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3762                              <1> ;;	it means relevant (respective) block is in use, and, 
  3763                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3764                              <1> ;;      swap disk/file block is free.
  3765                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3766                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3767                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3768                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3769                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3770                              <1> ;;	------------------------------------------------------------
  3771                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3772                              <1> ;;	------------------------------------------------------------
  3773                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3774                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3775                              <1> ;;
  3776                              <1> ;;	..............................................................
  3777                              <1> ;;
  3778                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3779                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3780                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3781                              <1> ;;	position with value of 1 on the table is converted to swap
  3782                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3783                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3784                              <1> ;;	number of physical swap disk or virtual swap disk)
  3785                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3786                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3787                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3788                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3789                              <1> ;;	If disk write procedure returns with error or free count of 
  3790                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3791                              <1> ;;	'insufficient memory error' (cf=1). 
  3792                              <1> ;;
  3793                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3794                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3795                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3796                              <1> ;;	free blocks after a disk write error. It will return to 
  3797                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3798                              <1> ;;
  3799                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3800                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3801                              <1> ;;	address (cf=0). 
  3802                              <1> ;;
  3803                              <1> ;;	..............................................................
  3804                              <1> ;;
  3805                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3806                              <1> ;;	file sectors at specified memory page. Then page allocation
  3807                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3808                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3809                              <1> ;;	to do, except to terminate the process which is the owner of
  3810                              <1> ;;	the swapped page.
  3811                              <1> ;;
  3812                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3813                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3814                              <1> ;;	updates [swpd_first] pointer if it is required.
  3815                              <1> ;;
  3816                              <1> ;;	..............................................................	 
  3817                              <1> ;;
  3818                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3819                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3820                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3821                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3822                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3823                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3824                              <1> ;;
  3825                              <1> 
  3826                              <1> ; 24/12/2021
  3827                              <1> ; ('swap_in' procedure call is disabled)
  3828                              <1> 
  3829                              <1> ;swap_in:
  3830                              <1> 	; 31/08/2015
  3831                              <1> 	; 20/07/2015
  3832                              <1> 	; 28/04/2015
  3833                              <1> 	; 18/04/2015
  3834                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3835                              <1> 	;
  3836                              <1> 	; INPUT -> 
  3837                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3838                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3839                              <1> 	;	EAX = Offset Address for the swapped page on the
  3840                              <1> 	;	      swap disk or in the swap file.
  3841                              <1> 	;
  3842                              <1> 	; OUTPUT ->
  3843                              <1> 	;	EAX = 0 if loading at memory has been successful
  3844                              <1> 	;
  3845                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3846                              <1> 	;		  or sector not present or drive not ready
  3847                              <1> 	;	     EAX = Error code
  3848                              <1> 	;	     [u.error] = EAX 
  3849                              <1> 	;		       = The last error code for the process
  3850                              <1> 	;		         (will be reset after returning to user)	  
  3851                              <1> 	;
  3852                              <1> 	; Modified Registers -> EAX
  3853                              <1> 	;
  3854                              <1> 
  3855                              <1> ;       cmp     dword [swp_drv], 0
  3856                              <1> ;	jna	short swpin_dnp_err
  3857                              <1> ;
  3858                              <1> ;	cmp	eax, [swpd_size]
  3859                              <1> ;	jnb	short swpin_snp_err
  3860                              <1> ;
  3861                              <1> ;	push	esi
  3862                              <1> ;	push	ebx
  3863                              <1> ;	push	ecx
  3864                              <1> ;	mov	esi, [swp_drv]	
  3865                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3866                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3867                              <1> ;		; size different than 512 bytes, logical disk sector
  3868                              <1> ;		; size is 512 bytes and disk reading procedure
  3869                              <1> ;		; will be performed for reading 4096 bytes
  3870                              <1> ;		; (2*2048, 8*512). 
  3871                              <1> ;	; ESI = Logical disk description table address
  3872                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3873                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3874                              <1> ;	; ECX = Sector count ; 8 sectors
  3875                              <1> ;	push	eax
  3876                              <1> ;	call	logical_disk_read
  3877                              <1> ;	pop	eax
  3878                              <1> ;	jnc	short swpin_read_ok
  3879                              <1> ;	;
  3880                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3881                              <1> ;	mov	[u.error], eax
  3882                              <1> ;	jmp	short swpin_retn
  3883                              <1> ;	;
  3884                              <1> ;swpin_read_ok:
  3885                              <1> ;	; EAX = Offset address (logical sector number)
  3886                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3887                              <1> ;	;
  3888                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3889                              <1> ;	; 20/07/2015
  3890                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3891                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3892                              <1> ;	mov	bl, [u.uno] ; current process number
  3893                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3894                              <1> ;	call	swap_queue_shift
  3895                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3896                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3897                              <1> ;	; zf = 1
  3898                              <1> ;swpin_retn:
  3899                              <1> ;	pop	ecx
  3900                              <1> ;	pop	ebx
  3901                              <1> ;	pop	esi
  3902                              <1> ;	retn
  3903                              <1> ;
  3904                              <1> ;swpin_dnp_err:
  3905                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3906                              <1> ;swpin_err_retn:
  3907                              <1> ;	mov	[u.error], eax
  3908                              <1> ;	stc
  3909                              <1> ;	retn
  3910                              <1> ;
  3911                              <1> ;swpin_snp_err:
  3912                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3913                              <1> ;	jmp	short swpin_err_retn
  3914                              <1> 
  3915                              <1> ; 24/12/2021
  3916                              <1> ; ('swap_out' procedure call is disabled)
  3917                              <1> 
  3918                              <1> ;swap_out:
  3919                              <1> 	; 10/06/2016
  3920                              <1> 	; 07/06/2016
  3921                              <1>         ; 23/05/2016
  3922                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3923                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3924                              <1> 	;
  3925                              <1> 	; INPUT -> 
  3926                              <1> 	;	none
  3927                              <1> 	;
  3928                              <1> 	; OUTPUT ->
  3929                              <1> 	;	EAX = Physical page address (which is swapped out
  3930                              <1> 	;	      for allocating a new page)
  3931                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3932                              <1> 	;		  or sector not present or drive not ready
  3933                              <1> 	;	     EAX = Error code
  3934                              <1> 	;	     [u.error] = EAX 
  3935                              <1> 	;		       = The last error code for the process
  3936                              <1> 	;		         (will be reset after returning to user)	  
  3937                              <1> 	;
  3938                              <1> 	; Modified Registers -> none (except EAX)
  3939                              <1> 	;
  3940                              <1> 
  3941                              <1> ;	cmp 	word [swpq_count], 1
  3942                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3943                              <1> ;
  3944                              <1> ;       ;cmp    dword [swp_drv], 1
  3945                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3946                              <1> ;
  3947                              <1> ;       cmp     dword [swpd_free], 1
  3948                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3949                              <1> ;
  3950                              <1> ;	push	ebx ; *
  3951                              <1> ;swpout_1:
  3952                              <1> ;	; 10/06/2016
  3953                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3954                              <1> ;	call	swap_queue_shift
  3955                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3956                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3957                              <1> ;				       ; pointer in the swap queue
  3958                              <1> ;	; EAX = PTE value of the page
  3959                              <1> ;	; EBX = PTE address of the page
  3960                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3961                              <1> ;	;
  3962                              <1> ;	; 07/06/2016
  3963                              <1> ;	; 19/05/2016
  3964                              <1> ;	; check this page is in timer events or not
  3965                              <1> ;	
  3966                              <1> ;swpout_timer_page_0:
  3967                              <1> ;	push	edx ; **
  3968                              <1> ;
  3969                              <1> ;	; 07/06/2016
  3970                              <1> ;	cmp	byte [timer_events], 0 
  3971                              <1> ;	jna	short swpout_2
  3972                              <1> ;	;
  3973                              <1> ;	mov	dl, [timer_events]
  3974                              <1> ;
  3975                              <1> ;	push	ecx ; ***
  3976                              <1> ;	push	ebx ; ****
  3977                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3978                              <1> ;			       ; structures 
  3979                              <1> ;swpout_timer_page_1:
  3980                              <1> ;	mov	cl, [ebx]
  3981                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  3982                              <1> ;	jz	short swpout_timer_page_3
  3983                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  3984                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  3985                              <1> ;				; of the response byte address, to
  3986                              <1> ;				; get beginning of the page address)
  3987                              <1> ;	cmp	eax, ecx
  3988                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  3989                              <1> ;	
  3990                              <1> ;	; !same page!
  3991                              <1> ;	;
  3992                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  3993                              <1> ;	; This page will be used by the kernel to put timer event
  3994                              <1> ;	; response (signal return) byte at the requested address;
  3995                              <1> ;	; in order to prevent a possible wrong write (while
  3996                              <1> ;	; this page is swapped out) on physical memory,
  3997                              <1> ;	; we must protect this page against to be swapped out!
  3998                              <1> ;	;
  3999                              <1> ;	pop	ebx ; ****
  4000                              <1> ;	pop	ecx ; ***
  4001                              <1> ;	pop	edx ; **
  4002                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4003                              <1> ; 
  4004                              <1> ;swpout_timer_page_2:
  4005                              <1> ;	; 07/06/2016
  4006                              <1> ;	dec	dl
  4007                              <1> ;	jz	short swpout_timer_page_4
  4008                              <1> ;swpout_timer_page_3:
  4009                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4010                              <1> ;	;jnb	short swpout_timer_page_4
  4011                              <1> ;	add	ebx, 16
  4012                              <1> ;	jmp	short swpout_timer_page_1	
  4013                              <1> ;
  4014                              <1> ;swpout_timer_page_4:
  4015                              <1> ;	pop	ebx ; ****
  4016                              <1> ;	pop	ecx ; ***
  4017                              <1> ;swpout_2:
  4018                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4019                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4020                              <1> ;	;
  4021                              <1> ;	call	link_swap_block
  4022                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4023                              <1> ;				       ; because [swpd_free] value
  4024                              <1> ;				       ; was checked at the beginging. 	
  4025                              <1> ;	pop	edx ; **
  4026                              <1> ;	pop	ebx ; *
  4027                              <1> ;	jmp	short swpout_nfspc_err 
  4028                              <1> ;swpout_3:
  4029                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4030                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4031                              <1> ;	;	
  4032                              <1> ;	push	esi ; **
  4033                              <1> ;	push	ecx ; ***
  4034                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4035                              <1> ;	mov	esi, [swp_drv]	
  4036                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4037                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4038                              <1> ;		; size different than 512 bytes, logical disk sector
  4039                              <1> ;		; size is 512 bytes and disk writing procedure
  4040                              <1> ;		; will be performed for writing 4096 bytes
  4041                              <1> ;		; (2*2048, 8*512). 
  4042                              <1> ;	; ESI = Logical disk description table address
  4043                              <1> ;	; EBX = Buffer (Page) address
  4044                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4045                              <1> ;	; ECX = Sector count ; 8 sectors
  4046                              <1> ;	; edx = PTE address
  4047                              <1> ;	call	logical_disk_write
  4048                              <1> ;	; edx = PTE address
  4049                              <1> ;	pop	ecx ; sector address	
  4050                              <1> ;	jnc	short swpout_write_ok
  4051                              <1> ;	;
  4052                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4053                              <1> ;swpout_dw_err:
  4054                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4055                              <1> ;	mov	[u.error], eax
  4056                              <1> ;	jmp	short swpout_retn
  4057                              <1> ;	;
  4058                              <1> ;swpout_write_ok:
  4059                              <1> ;	; EBX = Buffer (page) address
  4060                              <1> ;	; EDX = Page Table Entry address
  4061                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4062                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4063                              <1> ;	mov 	[edx], ecx 
  4064                              <1> ;		; bit 0 = 0 (swapped page)
  4065                              <1> ;	mov	eax, ebx
  4066                              <1> ;swpout_retn:
  4067                              <1> ;	pop	ecx ; ***
  4068                              <1> ;	pop	esi ; **
  4069                              <1> ;	pop	ebx ; *
  4070                              <1> ;	retn
  4071                              <1> ;
  4072                              <1> ;;swpout_dnp_err:
  4073                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4074                              <1> ;;	jmp	short swpout_err_retn
  4075                              <1> ;swpout_nfspc_err:
  4076                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4077                              <1> ;swpout_err_retn:
  4078                              <1> ;	mov	[u.error], eax
  4079                              <1> ;	;stc
  4080                              <1> ;	retn
  4081                              <1> ;swpout_npts_err:
  4082                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4083                              <1> ;	pop	ebx
  4084                              <1> ;	jmp	short swpout_err_retn
  4085                              <1> ;swpout_im_err:
  4086                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4087                              <1> ;	jmp	short swpout_err_retn
  4088                              <1> 
  4089                              <1> ; 24/12/2021
  4090                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4091                              <1> 
  4092                              <1> ;swap_queue_shift:
  4093                              <1> 	; 26/03/2017
  4094                              <1> 	; 10/06/2016
  4095                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4096                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4097                              <1> 	;
  4098                              <1> 	; INPUT ->
  4099                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4100                              <1> 	;	      and process number combination (bit 0 to 11)
  4101                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4102                              <1> 	;	
  4103                              <1> 	; OUTPUT ->
  4104                              <1> 	;	If EBX input > 0 
  4105                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4106                              <1> 	; 	   from the tail to the head, up to entry offset
  4107                              <1> 	; 	   which points to EBX input value or nothing
  4108                              <1> 	;	   to do if EBX value is not found on the queue.
  4109                              <1> 	;	   (The entry -with EBX value- will be removed
  4110                              <1> 	;	   from the queue if it is found.)
  4111                              <1> 	;
  4112                              <1> 	;	   EAX = 0		
  4113                              <1> 	;
  4114                              <1> 	;	If EBX input = 0
  4115                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4116                              <1> 	; 	   from the tail to the head, if the PTE address
  4117                              <1> 	;	   which is pointed in head of the queue is marked
  4118                              <1> 	;	   as "accessed" or it is marked as "non present".
  4119                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4120                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4121                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4122                              <1> 	;	   -without dropping pointer of the PTE from 
  4123                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4124                              <1> 	;	   Pointer in the head will be moved into the tail,
  4125                              <1> 	;	   other PTEs will be shifted on head direction.)
  4126                              <1> 	;
  4127                              <1> 	;	   Swap queue will be shifted up to the first
  4128                              <1> 	;	   'present' or 'non accessed' page will be found
  4129                              <1> 	;	   (as pointed) on the queue head (then it will be
  4130                              <1>         ;          removed/dropped from the queue).
  4131                              <1> 	;
  4132                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4133                              <1> 	;		 (it's pointer -virtual address-) dropped
  4134                              <1> 	;		 (removed) from swap queue.
  4135                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4136                              <1> 	;	         which is (it's pointer -virtual address-)
  4137                              <1> 	;		 dropped (removed) from swap queue.
  4138                              <1> 	;
  4139                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4140                              <1> 	;
  4141                              <1> 	; Modified Registers -> EAX, EBX
  4142                              <1> 	;
  4143                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4144                              <1> ;	and	ax, ax
  4145                              <1> ;	jz	short swpqs_retn
  4146                              <1> ;	push	edi
  4147                              <1> ;	push	esi
  4148                              <1> ;	push	ecx
  4149                              <1> ;	mov	esi, swap_queue
  4150                              <1> ;	mov	ecx, eax
  4151                              <1> ;	or	ebx, ebx
  4152                              <1> ;	jz	short swpqs_7
  4153                              <1> ;swpqs_1:
  4154                              <1> ;	lodsd
  4155                              <1> ;	cmp	eax, ebx
  4156                              <1> ;	je	short swpqs_2
  4157                              <1> ;	loop	swpqs_1
  4158                              <1> ;	; 10/06/2016
  4159                              <1> ;	sub	eax, eax 
  4160                              <1> ;	jmp	short swpqs_6
  4161                              <1> ;swpqs_2:
  4162                              <1> ;	mov	edi, esi
  4163                              <1> ;	sub 	edi, 4
  4164                              <1> ;swpqs_3:
  4165                              <1> ;	dec	word [swpq_count]
  4166                              <1> ;	jz	short swpqs_5
  4167                              <1> ;swpqs_4:
  4168                              <1> ;	dec 	ecx
  4169                              <1> ;	rep	movsd	; shift up (to the head)
  4170                              <1> ;swpqs_5:
  4171                              <1> ;	xor	eax, eax
  4172                              <1> ;	mov	[edi], eax
  4173                              <1> ;swpqs_6:
  4174                              <1> ;	pop	ecx
  4175                              <1> ;	pop	esi
  4176                              <1> ;	pop	edi
  4177                              <1> ;swpqs_retn:
  4178                              <1> ;	retn		
  4179                              <1> ;swpqs_7:
  4180                              <1> ;	mov	edi, esi ; head
  4181                              <1> ;	lodsd
  4182                              <1> ;	; 20/07/2015
  4183                              <1> ;	mov	ebx, eax
  4184                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4185                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4186                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4187                              <1> ;		      ; ax = process number (1 to 4095)
  4188                              <1> ;	cmp	al, [u.uno]
  4189                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4190                              <1> ;	jne	short swpqs_8
  4191                              <1> ;	mov	eax, [u.pgdir]
  4192                              <1> ;	jmp	short swpqs_9
  4193                              <1> ;swpqs_8:
  4194                              <1> ;	; 09/06/2016
  4195                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4196                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4197                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4198                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4199                              <1> ;
  4200                              <1> ;	;shl	ax, 2
  4201                              <1> ;	shl	al, 2
  4202                              <1> ;	mov 	eax, [eax+p.upage-4]
  4203                              <1> ;	or	eax, eax
  4204                              <1> ;	jz	short swpqs_3 ; invalid upage
  4205                              <1> ;	add	eax, u.pgdir - user
  4206                              <1> ;			 ; u.pgdir value for the process
  4207                              <1> ;			 ; is in [eax]
  4208                              <1> ;	mov	eax, [eax]
  4209                              <1> ;	and	eax, eax
  4210                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4211                              <1> ;swpqs_9:
  4212                              <1> ;	push	edx
  4213                              <1> ;	; eax = page directory
  4214                              <1> ;	; ebx = virtual address
  4215                              <1> ;	call	get_pte
  4216                              <1> ;	mov	ebx, edx	; PTE address
  4217                              <1> ;	pop	edx
  4218                              <1> ;	; 10/06/2016
  4219                              <1> ;	jc	short swpqs_13 ; empty PDE
  4220                              <1> ;	; EAX = PTE value
  4221                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4222                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4223                              <1> ;			        ; from the queue (head)
  4224                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4225                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4226                              <1> ;			        ; from the queue (head) 	
  4227                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4228                              <1> ;	;jnz	short swpqs_11  ; present
  4229                              <1> ;			        ; accessed page
  4230                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4231                              <1> ;	jc	short swpqs_11  ; accessed page
  4232                              <1> ;
  4233                              <1> ;	dec	ecx
  4234                              <1> ;	mov	[swpq_count], cx
  4235                              <1> ;       jz      short swpqs_10
  4236                              <1> ;		; esi = head + 4
  4237                              <1> ;		; edi = head
  4238                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4239                              <1> ;swpqs_10:
  4240                              <1> ;	mov	[edi], ecx ; 0
  4241                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4242                              <1> ;
  4243                              <1> ;swpqs_11:
  4244                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4245                              <1> ;	; Rotation (head -> tail)
  4246                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4247                              <1> ;	jz	short swpqs_10
  4248                              <1> ;		; esi = head + 4
  4249                              <1> ;		; edi = head
  4250                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4251                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4252                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4253                              <1> ;
  4254                              <1> ;	mov	cx, [swpq_count]
  4255                              <1> ;
  4256                              <1> ;swpqs_12:
  4257                              <1> ;	mov	esi, swap_queue ; head
  4258                              <1> ;       jmp     swpqs_7
  4259                              <1> ;
  4260                              <1> ;swpqs_13:
  4261                              <1> ;	dec	ecx
  4262                              <1> ;	mov	[swpq_count], cx
  4263                              <1> ;       jz      swpqs_5
  4264                              <1> ;	jmp	short swpqs_12
  4265                              <1> 
  4266                              <1> ; 24/12/2021
  4267                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4268                              <1> 
  4269                              <1> ;add_to_swap_queue:
  4270                              <1> 	; 20/02/2017
  4271                              <1> 	; 20/07/2015
  4272                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4273                              <1> 	;
  4274                              <1> 	; Adds new page to swap queue
  4275                              <1> 	; (page directories and page tables must not be added
  4276                              <1> 	; to swap queue)	
  4277                              <1> 	;
  4278                              <1> 	; INPUT ->
  4279                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4280                              <1> 	;	[u.uno]
  4281                              <1> 	;	20/02/2017
  4282                              <1> 	;	(Linear address = CORE + user's virtual address)
  4283                              <1> 	;
  4284                              <1> 	; OUTPUT ->
  4285                              <1> 	;	EAX = [swpq_count]
  4286                              <1> 	;	      (after the PTE has been added)
  4287                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4288                              <1> 	;	      the PTE could not be added.
  4289                              <1> 	;
  4290                              <1> 	; Modified Registers -> EAX
  4291                              <1> 	;
  4292                              <1> ;	push	ebx
  4293                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4294                              <1> ;	mov	bl, [u.uno] ; current process number
  4295                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4296                              <1> ;				 ; it is already on the queue
  4297                              <1> ;		; then add it to the tail of the queue
  4298                              <1> ;	movzx	eax, word [swpq_count]
  4299                              <1> ;	cmp	ax, 1024
  4300                              <1> ;	jb	short atsq_1
  4301                              <1> ;	sub	ax, ax
  4302                              <1> ;	pop	ebx
  4303                              <1> ;	retn
  4304                              <1> ;atsq_1:
  4305                              <1> ;	push	esi
  4306                              <1> ;	mov	esi, swap_queue
  4307                              <1> ;	and	ax, ax
  4308                              <1> ;	jz	short atsq_2
  4309                              <1> ;	shl	ax, 2	; convert to offset
  4310                              <1> ;	add	esi, eax
  4311                              <1> ;	shr	ax, 2
  4312                              <1> ;atsq_2:
  4313                              <1> ;	inc	ax
  4314                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4315                              <1> ;	mov	[swpq_count], ax
  4316                              <1> ;	pop	esi
  4317                              <1> ;	pop	ebx
  4318                              <1> ;	retn
  4319                              <1> 
  4320                              <1> ; 24/12/2021
  4321                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4322                              <1> 
  4323                              <1> ;unlink_swap_block:
  4324                              <1> 	; 15/09/2015
  4325                              <1> 	; 30/04/2015
  4326                              <1> 	; 18/04/2015
  4327                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4328                              <1> 	;
  4329                              <1> 	; INPUT -> 
  4330                              <1> 	;	EAX = swap disk/file offset address
  4331                              <1> 	;	      (bit 1 to bit 31)
  4332                              <1> 	; OUTPUT ->
  4333                              <1> 	;	[swpd_free] is increased
  4334                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4335                              <1> 	;
  4336                              <1> 	; Modified Registers -> EAX
  4337                              <1> 	;
  4338                              <1> ;	push	ebx
  4339                              <1> ;	push	edx
  4340                              <1> ;	;
  4341                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4342                              <1> ;				     ; 3 bits right
  4343                              <1> ;				     ; to get swap block/page number
  4344                              <1> ;	mov	edx, eax
  4345                              <1> ;	; 15/09/2015
  4346                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4347                              <1> ;				     ; (1 allocation bit = 1 page)
  4348                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4349                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4350                              <1> ;				     ; (to get 32 bit position)			
  4351                              <1> ;	;
  4352                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4353                              <1> ;	add	ebx, edx
  4354                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4355                              <1> ;				     ; (allocation bit position)	 
  4356                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4357                              <1> ;				     ; than the address in 'swpd_next' ?
  4358                              <1> ;				     ; (next/first free block value)		
  4359                              <1> ;	jnb	short uswpbl_1	     ; no	
  4360                              <1> ;	mov	[swpd_next], eax     ; yes	
  4361                              <1> ;uswpbl_1:
  4362                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4363                              <1> ;				     ; set relevant bit to 1.
  4364                              <1> ;				     ; set CF to the previous bit value	
  4365                              <1> ;	cmc			     ; complement carry flag	
  4366                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4367                              <1> ;				     ; if the block is already deallocated
  4368                              <1> ;				     ; before.	
  4369                              <1> ;       inc     dword [swpd_free]
  4370                              <1> ;uswpbl_2:
  4371                              <1> ;	pop	edx
  4372                              <1> ;	pop	ebx
  4373                              <1> ;	retn
  4374                              <1> 
  4375                              <1> ; 24/12/2021
  4376                              <1> ; ('link_swap_block' procedure call is disabled)
  4377                              <1> 
  4378                              <1> ;link_swap_block:
  4379                              <1> 	; 01/07/2015
  4380                              <1> 	; 18/04/2015
  4381                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4382                              <1> 	;
  4383                              <1> 	; INPUT -> none
  4384                              <1> 	;
  4385                              <1> 	; OUTPUT ->
  4386                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4387                              <1> 	;	      in sectors (corresponding 
  4388                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4389                              <1> 	;
  4390                              <1> 	;	CF = 1 and EAX = 0 
  4391                              <1> 	; 		   if there is not a free block to be allocated	
  4392                              <1> 	;
  4393                              <1> 	; Modified Registers -> none (except EAX)
  4394                              <1> 	;
  4395                              <1> 
  4396                              <1> ;	;mov	eax, [swpd_free]
  4397                              <1> ;	;and	eax, eax
  4398                              <1> ;	;jz	short out_of_swpspc
  4399                              <1> ;	;
  4400                              <1> ;	push	ebx
  4401                              <1> ;	push	ecx
  4402                              <1> ;	;
  4403                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4404                              <1> ;	mov	ecx, ebx
  4405                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4406                              <1> ;				 ; next_free_swap_block >> 5
  4407                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4408                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4409                              <1> ;lswbl_scan:
  4410                              <1> ;	cmp	ebx, ecx
  4411                              <1> ;	ja	short lswbl_notfound
  4412                              <1> ;	;
  4413                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4414                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4415                              <1> ;			   ; loads the destination with an index to
  4416                              <1> ;			   ; first set bit. (0 -> 31) 
  4417                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4418                              <1> ;	; 01/07/2015
  4419                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4420                              <1> ;			 ;
  4421                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4422                              <1> ;			 ;	  with value of 1 means 
  4423                              <1> ;			 ;	  the corresponding page is free 
  4424                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4425                              <1> ;	add	ebx, 4
  4426                              <1> ;			 ; We return back for searching next page block
  4427                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4428                              <1> ;			 ;	 we always will find at least 1 free block here.
  4429                              <1> ;	jmp    	short lswbl_scan
  4430                              <1> ;	;
  4431                              <1> ;lswbl_notfound:	
  4432                              <1> ;	sub	ecx, swap_alloc_table
  4433                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4434                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4435                              <1> ;	xor	eax, eax
  4436                              <1> ;	mov	[swpd_free], eax
  4437                              <1> ;	stc
  4438                              <1> ;lswbl_ok:
  4439                              <1> ;	pop	ecx
  4440                              <1> ;	pop	ebx
  4441                              <1> ;	retn
  4442                              <1> ;	;
  4443                              <1> ;;out_of_swpspc:
  4444                              <1> ;;	stc
  4445                              <1> ;;	retn
  4446                              <1> ;
  4447                              <1> ;lswbl_found:
  4448                              <1> ;	mov	ecx, ebx
  4449                              <1> ;	sub	ecx, swap_alloc_table
  4450                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4451                              <1> ;				 ; address/offset (to the next)
  4452                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4453                              <1> ;	;
  4454                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4455                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4456                              <1> ;				 ; in the destination.
  4457                              <1> ;				 ;
  4458                              <1> ;				 ; Reset the bit which is corresponding to the 
  4459                              <1> ;				 ; (just) allocated block.
  4460                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4461                              <1> ;	add	eax, ecx	 ; = block number
  4462                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4463                              <1> ;				 ; 1 block =  8 sectors
  4464                              <1> ;	;
  4465                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4466                              <1> ;	;
  4467                              <1> ;	; NOTE: The relevant page table entry will be updated
  4468                              <1> ;	;       according to this EAX value...
  4469                              <1> ;	;
  4470                              <1> ;	jmp	short lswbl_ok
  4471                              <1> 
  4472                              <1> ; 24/12/2021
  4473                              <1> ; ('logical_disk_read' procedure call is disabled)
  4474                              <1> 
  4475                              <1> ;logical_disk_read:
  4476                              <1> 	; 20/07/2015
  4477                              <1> 	; 09/03/2015 (temporary code here)
  4478                              <1> 	;
  4479                              <1> 	; INPUT ->
  4480                              <1> 	; 	ESI = Logical disk description table address
  4481                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4482                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4483                              <1> 	; 	ECX = Sector count
  4484                              <1> 	;
  4485                              <1> 	;
  4486                              <1> ;	retn
  4487                              <1> 
  4488                              <1> ; 24/12/2021
  4489                              <1> ; ('logical_disk_write' procedure call is disabled)
  4490                              <1> 
  4491                              <1> ;logical_disk_write:
  4492                              <1> 	; 20/07/2015
  4493                              <1> 	; 09/03/2015 (temporary code here)
  4494                              <1> 	;
  4495                              <1> 	; INPUT ->
  4496                              <1> 	; 	ESI = Logical disk description table address
  4497                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4498                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4499                              <1> 	; 	ECX = Sector count
  4500                              <1> 	;
  4501                              <1> ;	retn
  4502                              <1> 
  4503                              <1> get_physical_addr:
  4504                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4505                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4506                              <1> 	; 18/10/2015
  4507                              <1> 	; 29/07/2015
  4508                              <1> 	; 20/07/2015
  4509                              <1> 	; 04/06/2015
  4510                              <1> 	; 20/05/2015
  4511                              <1> 	; 28/04/2015
  4512                              <1> 	; 18/04/2015
  4513                              <1> 	; Get physical address
  4514                              <1> 	;     (allocates a new page for user if it is not present)
  4515                              <1> 	;	
  4516                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4517                              <1> 	; (buffer) address to physical address (of the buffer).)
  4518                              <1> 	; ('sys write', 'sys read' system calls...)
  4519                              <1> 	;
  4520                              <1> 	; INPUT ->
  4521                              <1> 	;	EBX = virtual address
  4522                              <1> 	;	u.pgdir = page directory (physical) address
  4523                              <1> 	;
  4524                              <1> 	; OUTPUT ->
  4525                              <1> 	;	EAX = physical address 
  4526                              <1> 	;	EBX = linear address	
  4527                              <1> 	;	EDX = physical address of the page frame
  4528                              <1> 	;	      (with attribute bits)
  4529                              <1> 	;	ECX = byte count within the page frame
  4530                              <1> 	;
  4531                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4532                              <1> 	;
  4533                              <1> 
  4534                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4535 000027C9 A1[53650000]        <1> 	mov	eax, [u.pgdir]
  4536                              <1> 
  4537                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4538                              <1> 	
  4539 000027CE 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4540                              <1> 	;
  4541                              <1> 	;mov	eax, [u.pgdir]
  4542 000027D4 E81AFDFFFF          <1> 	call	get_pte
  4543                              <1> 		; EDX = Page table entry address (if CF=0)
  4544                              <1> 	        ;       Page directory entry address (if CF=1)
  4545                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4546                              <1> 		; EAX = Page table entry value (page address)
  4547                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4548 000027D9 731C                <1> 	jnc	short gpa_1
  4549                              <1> 	;
  4550 000027DB E801FCFFFF          <1> 	call	allocate_page
  4551 000027E0 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4552                              <1> gpa_0:
  4553 000027E2 E86BFCFFFF          <1> 	call 	clear_page
  4554                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4555 000027E7 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4556                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4557                              <1> 			   ; (user, writable, present page)	
  4558 000027E9 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4559 000027EB A1[53650000]        <1> 	mov	eax, [u.pgdir]	
  4560 000027F0 E8FEFCFFFF          <1> 	call	get_pte
  4561 000027F5 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4562                              <1> gpa_1:
  4563                              <1> 	; EAX = PTE value, EDX = PTE address
  4564 000027F7 A801                <1> 	test 	al, PTE_A_PRESENT
  4565 000027F9 750A                <1> 	jnz	short gpa_3
  4566 000027FB 09C0                <1> 	or	eax, eax
  4567 000027FD 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4568                              <1> 
  4569                              <1> ; 24/12/2021
  4570                              <1> ; ('reload_page' procedure call is disabled)
  4571 000027FF EB2C                <1> 	jmp	short gpa_im_err
  4572                              <1> 
  4573                              <1> 	; 20/07/2015
  4574                              <1> ;	push	ebp
  4575                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4576                              <1> ;	; reload swapped page
  4577                              <1> ;	call	reload_page ; 28/04/2015
  4578                              <1> ;	pop	ebp
  4579                              <1> ;	jc	short gpa_retn
  4580                              <1> gpa_2:
  4581                              <1> ; 24/12/2021
  4582                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4583                              <1> 
  4584                              <1> 	; 20/07/2015
  4585                              <1> 	; 20/05/2015
  4586                              <1> 	; add this page to swap queue
  4587                              <1> ;	push	eax 
  4588                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4589                              <1> ;	call 	add_to_swap_queue
  4590                              <1> ;	pop	eax
  4591                              <1> 		; PTE address in EDX
  4592                              <1> 		; virtual address in EBX
  4593                              <1> 	; EAX = memory page address
  4594 00002801 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4595                              <1> 				  ; present flag, bit 0 = 1
  4596                              <1> 				  ; user flag, bit 2 = 1	
  4597                              <1> 				  ; writable flag, bit 1 = 1
  4598 00002803 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4599                              <1> gpa_3:
  4600                              <1> 	; 18/10/2015
  4601 00002805 89D9                <1> 	mov	ecx, ebx
  4602 00002807 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4603 0000280D 89C2                <1> 	mov 	edx, eax
  4604 0000280F 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4605 00002813 01C8                <1> 	add	eax, ecx
  4606 00002815 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4607 00002817 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4608 0000281D F8                  <1> 	clc
  4609                              <1> gpa_retn:
  4610 0000281E C3                  <1> 	retn	
  4611                              <1> gpa_4:	
  4612 0000281F E8BDFBFFFF          <1> 	call	allocate_page
  4613 00002824 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4614 00002826 E827FCFFFF          <1> 	call	clear_page
  4615 0000282B EBD4                <1> 	jmp	short gpa_2
  4616                              <1> 
  4617                              <1> gpa_im_err:	
  4618 0000282D B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4619                              <1> 				  ; Major error = 0 (No protection fault)	
  4620 00002832 C3                  <1> 	retn
  4621                              <1> 
  4622                              <1> ; 24/12/2021
  4623                              <1> ; ('reload_page' procedure call is disabled)
  4624                              <1> 
  4625                              <1> ;reload_page:
  4626                              <1> 	; 20/07/2015
  4627                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4628                              <1> 	;
  4629                              <1> 	; Reload (Restore) swapped page at memory
  4630                              <1> 	;
  4631                              <1> 	; INPUT -> 
  4632                              <1> 	;	EBP = Virtual (linear) memory address
  4633                              <1> 	;	EAX = PTE value (swap disk sector address)
  4634                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4635                              <1> 	; OUTPUT ->
  4636                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4637                              <1> 	;
  4638                              <1> 	;	CF = 1 and EAX = error code
  4639                              <1> 	;
  4640                              <1> 	; Modified Registers -> none (except EAX)
  4641                              <1> 	;
  4642                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4643                              <1> ;	push	ebx      ;
  4644                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4645                              <1> ;	call	allocate_page
  4646                              <1> ;	jc	short rlp_im_err
  4647                              <1> ;	xchg 	eax, ebx	
  4648                              <1> ;	; EBX = Physical memory (page) address
  4649                              <1> ;	; EAX = Swap disk (offset) address
  4650                              <1> ;	; EBP = Virtual (linear) memory address
  4651                              <1> ;	call	swap_in
  4652                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4653                              <1> ;	mov	eax, ebx	
  4654                              <1> ;rlp_retn:
  4655                              <1> ;	pop	ebx
  4656                              <1> ;	retn
  4657                              <1> ;	
  4658                              <1> ;rlp_im_err:	
  4659                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4660                              <1> ;				  ; Major error = 0 (No protection fault)	
  4661                              <1> ;	jmp	short rlp_retn
  4662                              <1> ;
  4663                              <1> ;rlp_swp_err:
  4664                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4665                              <1> ;	jmp	short rlp_retn
  4666                              <1> 
  4667                              <1> copy_page_dir:
  4668                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4669                              <1> 	; 19/09/2015
  4670                              <1> 	; temporary - 07/09/2015
  4671                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4672                              <1> 	;
  4673                              <1> 	; INPUT -> 
  4674                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4675                              <1> 	;		    page directory.
  4676                              <1> 	; OUTPUT ->
  4677                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4678                              <1> 	;	       page directory.
  4679                              <1> 	;	(New page directory with new page table entries.)
  4680                              <1> 	;	(New page tables with read only copies of the parent's
  4681                              <1> 	;	pages.)
  4682                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4683                              <1> 	;
  4684                              <1> 	; Modified Registers -> none (except EAX)
  4685                              <1> 	;
  4686 00002833 E8A9FBFFFF          <1> 	call	allocate_page
  4687 00002838 723E                <1> 	jc	short cpd_err
  4688                              <1> 	;
  4689 0000283A 55                  <1> 	push	ebp ; 20/07/2015
  4690 0000283B 56                  <1> 	push	esi
  4691 0000283C 57                  <1> 	push	edi
  4692 0000283D 53                  <1> 	push	ebx
  4693 0000283E 51                  <1> 	push	ecx
  4694 0000283F 8B35[53650000]      <1> 	mov	esi, [u.pgdir]
  4695 00002845 89C7                <1> 	mov	edi, eax
  4696 00002847 50                  <1> 	push	eax ; save child's page directory address
  4697                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4698                              <1> 	; (use same system space for all user page tables) 
  4699 00002848 A5                  <1> 	movsd
  4700 00002849 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4701 0000284E B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4702                              <1> cpd_0:	
  4703 00002853 AD                  <1> 	lodsd
  4704                              <1> 	;or	eax, eax
  4705                              <1>         ;jnz	short cpd_1
  4706 00002854 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4707 00002856 7508                <1> 	jnz	short cpd_1
  4708                              <1>  	; (virtual address at the end of the page table)	
  4709 00002858 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4710 0000285E EB0F                <1> 	jmp	short cpd_2
  4711                              <1> cpd_1:	
  4712 00002860 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4713 00002864 89C3                <1> 	mov	ebx, eax
  4714                              <1> 	; EBX = Parent's page table address
  4715 00002866 E81F000000          <1> 	call	copy_page_table
  4716 0000286B 720C                <1> 	jc	short cpd_p_err
  4717                              <1> 	; EAX = Child's page table address
  4718 0000286D 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4719                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4720                              <1> 			 ; (present, writable, user)
  4721                              <1> cpd_2:
  4722 0000286F AB                  <1> 	stosd
  4723 00002870 E2E1                <1> 	loop	cpd_0
  4724                              <1> 	;
  4725 00002872 58                  <1> 	pop	eax  ; restore child's page directory address
  4726                              <1> cpd_3:
  4727 00002873 59                  <1> 	pop	ecx
  4728 00002874 5B                  <1> 	pop	ebx
  4729 00002875 5F                  <1> 	pop	edi
  4730 00002876 5E                  <1> 	pop	esi
  4731 00002877 5D                  <1> 	pop	ebp
  4732                              <1> cpd_err:
  4733 00002878 C3                  <1> 	retn
  4734                              <1> cpd_p_err:
  4735                              <1> 	; release the allocated pages missing (recover free space)
  4736 00002879 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4737 0000287A 8B1D[53650000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4738 00002880 E88CFCFFFF          <1> 	call 	deallocate_page_dir
  4739 00002885 29C0                <1> 	sub	eax, eax ; 0
  4740 00002887 F9                  <1> 	stc
  4741 00002888 EBE9                <1> 	jmp	short cpd_3	
  4742                              <1> 
  4743                              <1> copy_page_table:
  4744                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4745                              <1> 	; 19/09/2015
  4746                              <1> 	; temporary - 07/09/2015
  4747                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4748                              <1> 	;
  4749                              <1> 	; INPUT -> 
  4750                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4751                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4752                              <1> 	; OUTPUT ->
  4753                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4754                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4755                              <1> 	;	CF = 1 -> error 
  4756                              <1> 	;
  4757                              <1> 	; Modified Registers -> EBP (except EAX)
  4758                              <1> 	;
  4759 0000288A E852FBFFFF          <1> 	call	allocate_page
  4760 0000288F 7244                <1> 	jc	short cpt_err
  4761                              <1> 	;
  4762 00002891 50                  <1> 	push	eax ; *
  4763                              <1> 	;push 	ebx
  4764 00002892 56                  <1> 	push	esi
  4765 00002893 57                  <1> 	push	edi
  4766 00002894 52                  <1> 	push	edx
  4767 00002895 51                  <1> 	push	ecx
  4768                              <1> 	;
  4769 00002896 89DE                <1> 	mov	esi, ebx
  4770 00002898 89C7                <1> 	mov	edi, eax
  4771 0000289A 89C2                <1> 	mov	edx, eax
  4772 0000289C 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4773                              <1> cpt_0:
  4774 000028A2 AD                  <1> 	lodsd
  4775 000028A3 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4776                              <1> 	;jnz	short cpt_1 (*)
  4777                              <1> 	; 24/12/2021
  4778                              <1> 	;and	eax, eax (*)
  4779 000028A5 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4780                              <1> 	
  4781                              <1> ; 24/12/2021
  4782                              <1> ; ('reload_page' procedure call is disabled)
  4783                              <1> ;
  4784                              <1> ;	; ebp = virtual (linear) address of the memory page
  4785                              <1> ;	call	reload_page ; 28/04/2015
  4786                              <1> ;	jc	short cpt_p_err
  4787                              <1> cpt_1:
  4788 000028A7 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4789 000028AB 89C1                <1> 	mov	ecx, eax
  4790                              <1> 	; Allocate a new page for the child process
  4791 000028AD E82FFBFFFF          <1> 	call	allocate_page
  4792 000028B2 721C                <1> 	jc	short cpt_p_err
  4793 000028B4 57                  <1> 	push	edi
  4794 000028B5 56                  <1> 	push	esi
  4795 000028B6 89CE                <1> 	mov	esi, ecx
  4796 000028B8 89C7                <1> 	mov	edi, eax
  4797 000028BA B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4798 000028BF F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4799 000028C1 5E                  <1> 	pop	esi
  4800 000028C2 5F                  <1> 	pop	edi
  4801                              <1> 	; 
  4802                              <1> ; 24/12/2021
  4803                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4804                              <1> ;
  4805                              <1> ;	push	ebx
  4806                              <1> ;	push	eax
  4807                              <1> ;	mov	ebx, ebp
  4808                              <1> ;	; ebx = virtual address of the memory page
  4809                              <1> ;	call	add_to_swap_queue
  4810                              <1> ;	pop	eax
  4811                              <1> ;	pop	ebx
  4812                              <1> 	;
  4813                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4814 000028C3 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4815                              <1> cpt_2:
  4816 000028C5 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4817                              <1> 	;
  4818 000028C6 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4819                              <1> 	;
  4820 000028CC 39D7                <1> 	cmp	edi, edx
  4821 000028CE 72D2                <1> 	jb	short cpt_0
  4822                              <1> cpt_p_err:
  4823 000028D0 59                  <1> 	pop	ecx
  4824 000028D1 5A                  <1> 	pop	edx
  4825 000028D2 5F                  <1> 	pop	edi
  4826 000028D3 5E                  <1> 	pop	esi
  4827                              <1> 	;pop	ebx
  4828 000028D4 58                  <1> 	pop	eax ; *
  4829                              <1> cpt_err:
  4830 000028D5 C3                  <1> 	retn
  4831                              <1> 
  4832                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4833                              <1> 
  4834                              <1> ;; Data:
  4835                              <1> 
  4836                              <1> ; 09/03/2015
  4837                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4838                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4839                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4840                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4841                              <1> ;swpd_next:  dd 0 ; next free page block
  4842                              <1> ;swpd_last:  dd 0 ; last swap page block
  2050                                  %include 'sysdefs.inc' ; 09/03/2015
  2051                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYSDEFS.INC
  2052                              <1> ; Last Modification: 15/07/2022
  2053                              <1> ;
  2054                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2055                              <1> ; (Modified from 
  2056                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2057                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2058                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2059                              <1> ; ----------------------------------------------------------------------------
  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> ; ****************************************************************************
  2067                              <1> 
  2068                              <1> nproc 	equ	16  ; number of processes
  2069                              <1> nfiles 	equ	50
  2070                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2071                              <1> ;nbuf	equ	6   ; number of buffers (04/02/2016)
  2072                              <1> nbuf	equ	8   ; 15/07/2022	  	
  2073                              <1> 
  2074                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2075                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2076                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2077                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2078                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2079                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2080                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2081                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2082                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2083                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2084                              <1> 	; '/core' dump file size = 32768 bytes
  2085                              <1>  
  2086                              <1> ; 08/03/2014 
  2087                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2088                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feature only !
  2089                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2090                              <1> 
  2091                              <1> ; 30/08/2013
  2092                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2093                              <1> 
  2094                              <1> ; 05/02/2014
  2095                              <1> ; process status
  2096                              <1> ;SFREE 	equ 0
  2097                              <1> ;SRUN	equ 1
  2098                              <1> ;SWAIT	equ 2
  2099                              <1> ;SZOMB	equ 3
  2100                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2101                              <1> 
  2102                              <1> ; 09/03/2015
  2103                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2104                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2105                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2106                              <1> 
  2107                              <1> ; 17/09/2015
  2108                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2109                              <1> 
  2110                              <1> ; 21/09/2015 (36) 
  2111                              <1> ; 01/07/2015 (35)
  2112                              <1> ; 14/07/2013 (0-34)
  2113                              <1> ; UNIX v1 system calls
  2114                              <1> _rele 	equ 0
  2115                              <1> _exit 	equ 1
  2116                              <1> _fork 	equ 2
  2117                              <1> _read 	equ 3
  2118                              <1> _write	equ 4
  2119                              <1> _open	equ 5
  2120                              <1> _close 	equ 6
  2121                              <1> _wait 	equ 7
  2122                              <1> _creat 	equ 8
  2123                              <1> _link 	equ 9
  2124                              <1> _unlink	equ 10
  2125                              <1> _exec	equ 11
  2126                              <1> _chdir	equ 12
  2127                              <1> _time 	equ 13
  2128                              <1> _mkdir 	equ 14
  2129                              <1> _chmod	equ 15
  2130                              <1> _chown	equ 16
  2131                              <1> _break	equ 17
  2132                              <1> _stat	equ 18
  2133                              <1> _seek	equ 19
  2134                              <1> _tell 	equ 20
  2135                              <1> _mount	equ 21
  2136                              <1> _umount	equ 22
  2137                              <1> _setuid	equ 23
  2138                              <1> _getuid	equ 24
  2139                              <1> _stime	equ 25
  2140                              <1> _quit	equ 26	
  2141                              <1> _intr	equ 27
  2142                              <1> _fstat	equ 28
  2143                              <1> _emt 	equ 29
  2144                              <1> _mdate 	equ 30
  2145                              <1> _stty 	equ 31
  2146                              <1> _gtty	equ 32
  2147                              <1> _ilgins	equ 33
  2148                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2149                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2150                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2151                              <1> 
  2152                              <1> %macro sys 1-4
  2153                              <1>     ; 13/04/2015
  2154                              <1>     ; Retro UNIX 386 v1 system call.		
  2155                              <1>     mov eax, %1
  2156                              <1>     %if %0 >= 2   
  2157                              <1>         mov ebx, %2
  2158                              <1>         %if %0 >= 3    
  2159                              <1>             mov ecx, %3
  2160                              <1>             %if %0 = 4
  2161                              <1>                mov edx, %4   
  2162                              <1>             %endif
  2163                              <1>         %endif
  2164                              <1>     %endif
  2165                              <1>     int 30h	   
  2166                              <1> %endmacro
  2167                              <1> 
  2168                              <1> ; 13/05/2015 - ERROR CODES
  2169                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2170                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2171                              <1> ; 14/05/2015
  2172                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2173                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2174                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2175                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2176                              <1> ; 16/05/2015		
  2177                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2178                              <1> ; 18/05/2015
  2179                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2180                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2181                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2182                              <1> ; 07/06/2015
  2183                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2184                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2185                              <1> ; 09/06/2015
  2186                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2187                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2188                              <1> ; 16/06/2015
  2189                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2190                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2191                              <1> ; 22/06/2015
  2192                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2193                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2194                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2195                              <1> ; 23/06/2015
  2196                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2197                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2198                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2199                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2200                              <1> ; 27/06/2015
  2201                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2202                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2203                              <1> ; 29/06/2015
  2204                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2205                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2206                              <1> ; 12/02/2022 
  2207                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2208                              <1> ; 10/10/2016
  2209                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2210                              <1> ; 18/05/2016
  2211                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2212                              <1> ; 15/10/2016
  2213                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2214                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2215                              <1> ; 16/10/2016
  2216                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2217                              <1> ; 08/02/2022
  2218                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2219                              <1> 
  2220                              <1> ; 13/06/2022
  2221                              <1> ; printer errors
  2222                              <1> ERR_PRN_NOT_RDY	   equ 15 ; 'device not ready !' error
  2223                              <1> ERR_PRN_TIMEOUT	   equ 25 ; 'time out !' error
  2224                              <1> ERR_PRN_PAPER	   equ 31 ; 'out of paper !' error
  2225                              <1> ERR_PRN_IO	   equ 32 ; 'io error !' error
  2226                              <1> ERR_PRN_BUSY	   equ 34 ; 'busy !' error	
  2227                              <1> 
  2228                              <1> ; 26/08/2015
  2229                              <1> ; 24/07/2015
  2230                              <1> ; 24/06/2015
  2231                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2232                              <1> ; 01/07/2015
  2233                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2234                              <1> ;	 					 		
  2051                                  %include 'u0.s'        ; 15/03/2015
  2052                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS0.INC
  2053                              <1> ; Last Modification: 17/07/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 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2064                              <1> ;
  2065                              <1> ; ****************************************************************************
  2066                              <1> ; 21/11/2015
  2067                              <1> 
  2068                              <1> sys_init:
  2069                              <1> 	; 27/02/2022
  2070                              <1> 	; 23/02/2022
  2071                              <1> 	; 04/02/2022
  2072                              <1> 	; 18/10/2015
  2073                              <1> 	; 28/08/2015
  2074                              <1> 	; 24/08/2015
  2075                              <1> 	; 14/08/2015
  2076                              <1> 	; 24/07/2015 
  2077                              <1> 	; 02/07/2015
  2078                              <1> 	; 01/07/2015
  2079                              <1> 	; 23/06/2015
  2080                              <1> 	; 15/04/2015
  2081                              <1> 	; 13/04/2015
  2082                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2083                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2084                              <1> 	;
  2085                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2086                              <1> 	;
  2087                              <1> 	; 14/02/2014
  2088                              <1> 	; 14/07/2013
  2089                              <1> 	;;mov	ax, 41
  2090                              <1> 	; 27/02/2022
  2091                              <1> 	;xor	eax, eax
  2092                              <1> 	;mov	al, 41
  2093                              <1> 	;mov	[rootdir], ax
  2094                              <1> 	;mov	[u.cdir], ax
  2095                              <1> 	;;and	al, 1 ; 15/04/2015
  2096                              <1> 	;inc	al  ; ax = 1
  2097 000028D6 B001                <1> 	mov	al, 1
  2098 000028D8 A2[49650000]        <1> 	mov	[u.uno], al
  2099                              <1> 	;mov	[mpid], ax
  2100                              <1> 	;mov	[p.pid], ax
  2101 000028DD A2[EC640000]        <1> 	mov	[mpid], al
  2102 000028E2 A2[14620000]        <1> 	mov	[p.pid], al	
  2103 000028E7 A2[74620000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2104                              <1> 	; 27/02/2022
  2105 000028EC B029                <1> 	mov	al, 41
  2106                              <1> 	;mov	[rootdir], ax
  2107                              <1> 	;mov	[u.cdir], ax
  2108 000028EE A2[EE640000]        <1> 	mov	[rootdir], al
  2109 000028F3 A2[04650000]        <1> 	mov	[u.cdir], al
  2110                              <1> 	;
  2111                              <1> 	; 23/02/2022
  2112                              <1>  	;call	epoch
  2113                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2114                              <1> 	; 17/07/2013
  2115 000028F8 E888060000          <1> 	call 	bf_init ; buffer initialization
  2116                              <1> 	; 23/02/2022
  2117                              <1> 	; (save sysinit time on sb0)
  2118 000028FD E830030000          <1> 	call	epoch
  2119 00002902 A3[54770000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2120                              <1> 	; 23/06/2015
  2121 00002907 E8D5FAFFFF          <1> 	call	allocate_page
  2122                              <1> 	;;jc	error
  2123                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2124                              <1> 	; 04/02/2022
  2125 0000290C 7305                <1> 	jnc	short sysinit_1
  2126 0000290E E990000000          <1> 	jmp	panic
  2127                              <1> sysinit_1:
  2128 00002913 A3[4A650000]        <1> 	mov	[u.upage], eax ; user structure page	
  2129 00002918 A3[84620000]        <1> 	mov	[p.upage], eax
  2130                              <1> 	;
  2131 0000291D E830FBFFFF          <1> 	call	clear_page
  2132                              <1> 	;
  2133                              <1> 	; 14/08/2015
  2134 00002922 FA                  <1> 	cli
  2135                              <1> 	; 14/03/2015
  2136                              <1> 	; 17/01/2014
  2137 00002923 E8D7010000          <1> 	call	sp_init ; serial port initialization
  2138                              <1> 	; 14/08/2015
  2139 00002928 FB                  <1> 	sti
  2140                              <1> 	;
  2141                              <1> 	; 30/06/2015
  2142                              <1> 	;mov	esi, kernel_init_ok_msg
  2143                              <1> 	;call 	print_msg
  2144                              <1> 	;
  2145 00002929 30DB                <1> 	xor	bl, bl ; video page 0
  2146                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2147 0000292B E83C0F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2148 00002930 FEC3                <1> 	inc	bl
  2149 00002932 80FB08              <1> 	cmp	bl, 8
  2150 00002935 72F4                <1> 	jb	short vp_clr_nxt
  2151                              <1> 	;
  2152                              <1> 	; 24/07/2015
  2153                              <1> 	;push	KDATA
  2154                              <1>         ;push	esp
  2155                              <1> 	;mov	[tss.esp0], esp
  2156                              <1>         ;mov	word [tss.ss0], KDATA
  2157                              <1> 	;
  2158                              <1> 	; 27/02/2022
  2159                              <1> 	; 24/08/2015
  2160                              <1> 	;; temporary (01/07/2015)
  2161                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2162                              <1> 			       ; it is not needed here !
  2163                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2164 00002937 FE0D[F5640000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2165                              <1> 			      ; 0 = executing a system call
  2166                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2167                              <1> 	;
  2168                              <1> 	;;; 06/08/2015
  2169                              <1> 	;;;call	getch ; wait for a key stroke
  2170                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2171                              <1> ;;sys_init_msg_wait:
  2172                              <1> ;;	push 	ecx
  2173                              <1> ;;	mov	al, 1
  2174                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2175                              <1> ;;	call	getc_n
  2176                              <1> ;;	pop	ecx
  2177                              <1> ;;	jnz	short sys_init_msg_ok
  2178                              <1> ;;	loop	sys_init_msg_wait
  2179                              <1> 	;
  2180                              <1> ;;sys_init_msg_ok:
  2181                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2182 0000293D 6A10                <1> 	push	KDATA ; ss
  2183 0000293F 54                  <1> 	push	esp
  2184 00002940 9C                  <1> 	pushfd
  2185 00002941 6A08                <1> 	push	KCODE ; cs
  2186 00002943 68[77290000]        <1> 	push	init_exec ; eip
  2187 00002948 8925[F8640000]      <1> 	mov	[u.sp], esp
  2188 0000294E 1E                  <1> 	push	ds
  2189 0000294F 06                  <1> 	push	es
  2190 00002950 0FA0                <1> 	push	fs
  2191 00002952 0FA8                <1> 	push	gs	
  2192 00002954 60                  <1> 	pushad
  2193 00002955 8925[FC640000]      <1> 	mov	[u.usp], esp
  2194 0000295B E8AD1B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2195                              <1> 		      ; and interrupt return components (for IRET)
  2196 00002960 61                  <1> 	popad
  2197 00002961 6658                <1> 	pop	ax ; gs
  2198 00002963 6658                <1> 	pop	ax ; fs
  2199 00002965 6658                <1> 	pop	ax ; es
  2200 00002967 6658                <1> 	pop	ax ; ds	
  2201 00002969 58                  <1> 	pop	eax ; eip (init_exec)
  2202 0000296A 6658                <1> 	pop	ax ; cs (KCODE)
  2203 0000296C 58                  <1> 	pop	eax ; E-FLAGS
  2204 0000296D 58                  <1> 	pop	eax ; esp
  2205 0000296E 6658                <1> 	pop	ax ; ss (KDATA)
  2206                              <1> 	;
  2207 00002970 31C0                <1> 	xor	eax, eax ; 0
  2208 00002972 A3[57650000]        <1> 	mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2209                              <1> 	;
  2210                              <1> 	; 02/07/2015
  2211                              <1> 	; [u.pgdir ] = [k_page_dir]
  2212                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2213                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2214                              <1> init_exec:
  2215                              <1> 	; 13/03/2013
  2216                              <1> 	; 24/07/2013
  2217 00002977 BB[99290000]        <1> 	mov	ebx, init_file
  2218 0000297C B9[91290000]        <1> 	mov	ecx, init_argp
  2219                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2220                              <1> 	; ECX contains address of argument list pointer
  2221                              <1> 	;
  2222                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2223                              <1> 			      ; 0 = executing a system call
  2224                              <1> 	sys	_exec  ; execute file
  2153                              <2> 
  2154                              <2> 
  2155 00002981 B80B000000          <2>  mov eax, %1
  2156                              <2>  %if %0 >= 2
  2157                              <2>  mov ebx, %2
  2158                              <2>  %if %0 >= 3
  2159                              <2>  mov ecx, %3
  2160                              <2>  %if %0 = 4
  2161                              <2>  mov edx, %4
  2162                              <2>  %endif
  2163                              <2>  %endif
  2164                              <2>  %endif
  2165 00002986 CD30                <2>  int 30h
  2225 00002988 7319                <1> 	jnc	short panic
  2226                              <1> 	;
  2227 0000298A BE[4E5E0000]        <1> 	mov	esi, etc_init_err_msg
  2228                              <1> 	; 27/02/2022
  2229                              <1> 	;call 	print_msg
  2230 0000298F EB17                <1> 	jmp	short key_to_reboot
  2231                              <1> 
  2232                              <1> ;align 4
  2233                              <1> init_argp:
  2234 00002991 [99290000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2235                              <1> init_file:
  2236                              <1> 	; 24/08/2015
  2237 00002999 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2237 000029A2 00                  <1>
  2238                              <1> panic:
  2239                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2240                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2241 000029A3 BE[335E0000]        <1> 	mov 	esi, panic_msg
  2242                              <1> key_to_reboot: ; 27/02/2022
  2243 000029A8 E819000000          <1> 	call 	print_msg
  2244                              <1> ;key_to_reboot:
  2245                              <1> 	; 15/11/2015
  2246 000029AD E8D12B0000          <1> 	call 	getch 
  2247                              <1> 		; wait for a character from the current tty
  2248                              <1> 	;
  2249 000029B2 B00A                <1> 	mov	al, 0Ah
  2250 000029B4 8A1D[66610000]      <1> 	mov	bl, [ptty] ; [active_page]
  2251 000029BA B407                <1> 	mov	ah, 07h ; Black background, 
  2252                              <1> 			; light gray forecolor
  2253 000029BC E8F4E8FFFF          <1> 	call 	write_tty
  2254 000029C1 E993E5FFFF          <1> 	jmp	cpu_reset 
  2255                              <1> 
  2256                              <1> print_msg:
  2257                              <1> 	; 01/07/2015
  2258                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2259                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2260                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2261                              <1> 	;
  2262                              <1> 	;
  2263 000029C6 AC                  <1> 	lodsb
  2264                              <1> pmsg1:
  2265 000029C7 56                  <1> 	push 	esi
  2266 000029C8 0FB61D[66610000]    <1> 	movzx	ebx, byte [ptty]
  2267 000029CF B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2268 000029D1 E8DFE8FFFF          <1> 	call 	write_tty
  2269 000029D6 5E                  <1> 	pop	esi
  2270 000029D7 AC                  <1> 	lodsb
  2271 000029D8 20C0                <1> 	and 	al, al
  2272 000029DA 75EB                <1> 	jnz 	short pmsg1
  2273 000029DC C3                  <1> 	retn
  2274                              <1> 	
  2275                              <1> ctrlbrk:
  2276                              <1> 	; 04/02/2022
  2277                              <1> 	; 01/02/2022
  2278                              <1> 	; 12/11/2015
  2279                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2280                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2281                              <1> 	;
  2282                              <1> 	; INT 1Bh (control+break) handler
  2283                              <1> 	;
  2284                              <1>       	; Retro Unix 8086 v1 feature only!
  2285                              <1>       	;
  2286 000029DD 66833D[3E650000]00  <1> 	cmp 	word [u.intr], 0
  2287 000029E5 764B                <1> 	jna 	short cbrk4
  2288                              <1> cbrk0:
  2289                              <1> 	; 12/11/2015
  2290                              <1> 	; 06/12/2013
  2291 000029E7 66833D[40650000]00  <1> 	cmp 	word [u.quit], 0
  2292 000029EF 7441                <1> 	jz	short cbrk4
  2293                              <1> 	;
  2294                              <1> 	; 20/09/2013	
  2295                              <1> 	;push 	ax
  2296                              <1> 	; 01/02/2022
  2297 000029F1 50                  <1> 	push	eax
  2298                              <1> 
  2299                              <1> 	; 04/02/2022
  2300                              <1> 	; (repetitive ctrl+brk check) 
  2301 000029F2 66A1[40650000]      <1> 	mov	ax, [u.quit]
  2302 000029F8 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2303 000029FA 7435                <1> 	jz	short cbrk3
  2304                              <1> 
  2305                              <1> 	; 20/09/2013
  2306 000029FC A0[66610000]        <1> 	mov	al, [ptty]
  2307                              <1> 	;
  2308                              <1> 	; 12/11/2015
  2309                              <1> 	;
  2310                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2311                              <1> 	; or ctrl+break from console (pseudo) tty
  2312                              <1> 	; (!redirection!)
  2313                              <1> 	;
  2314 00002A01 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2315 00002A03 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2316                              <1> 	;	
  2317                              <1> 	; Serial port interrupt handler sets [ptty]
  2318                              <1> 	; to the port's tty number (as temporary).
  2319                              <1> 	;
  2320                              <1> 	; If active process is using a stdin or 
  2321                              <1> 	; stdout redirection (by the shell),
  2322                              <1>         ; console tty keyboard must be available
  2323                              <1> 	; to terminate running process,
  2324                              <1> 	; in order to prevent a deadlock. 
  2325                              <1> 	;
  2326 00002A05 52                  <1> 	push	edx
  2327 00002A06 0FB615[49650000]    <1> 	movzx	edx, byte [u.uno]
  2328 00002A0D 3A82[53620000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2329 00002A13 5A                  <1> 	pop	edx
  2330 00002A14 7412                <1> 	je	short cbrk2
  2331                              <1> cbrk1:
  2332 00002A16 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2333                              <1> 	; 06/12/2013
  2334 00002A18 3A05[30650000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2335 00002A1E 7408                <1> 	je	short cbrk2	
  2336 00002A20 3A05[31650000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2337 00002A26 7509                <1> 	jne	short cbrk3	
  2338                              <1> cbrk2:
  2339                              <1> 	;; 06/12/2013
  2340                              <1> 	;mov	ax, [u.quit]
  2341                              <1> 	;and	ax, ax
  2342                              <1> 	;jz	short cbrk3
  2343                              <1> 	;
  2344                              <1> 	;xor	ax, ax ; 0
  2345                              <1> 	;dec	ax
  2346                              <1> 	; 01/02/2022
  2347 00002A28 31C0                <1> 	xor	eax, eax ; 0
  2348 00002A2A 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2349                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2350 00002A2B 66A3[40650000]      <1> 	mov	[u.quit], ax
  2351                              <1> cbrk3:
  2352                              <1> 	;pop	ax
  2353                              <1> 	; 01/02/2022
  2354 00002A31 58                  <1> 	pop	eax
  2355                              <1> cbrk4:
  2356 00002A32 C3                  <1> 	retn
  2357                              <1> 
  2358                              <1> com2_int:
  2359                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2360                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2361                              <1> 	; 07/11/2015 
  2362                              <1> 	; 24/10/2015
  2363                              <1> 	; 23/10/2015
  2364                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2365                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2366                              <1> 	; < serial port 2 interrupt handler >
  2367                              <1> 	;
  2368 00002A33 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2369                              <1> 	;;push	eax
  2370                              <1> 	; 08/01/2022
  2371 00002A36 29C0                <1> 	sub	eax, eax
  2372 00002A38 B009                <1> 	mov	al, 9
  2373                              <1> 	;mov	ax, 9
  2374 00002A3A EB07                <1> 	jmp	short comm_int
  2375                              <1> com1_int:
  2376                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2377                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2378                              <1> 	; 07/11/2015
  2379                              <1> 	; 24/10/2015
  2380 00002A3C 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2381                              <1> 	; 23/10/2015
  2382                              <1> 	;push	eax
  2383                              <1> 	; 08/01/2022
  2384 00002A3F 29C0                <1> 	sub	eax, eax
  2385 00002A41 B008                <1> 	mov	al, 8
  2386                              <1> 	;mov	ax, 8
  2387                              <1> comm_int:
  2388                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2389                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2390                              <1> 	; 20/11/2015
  2391                              <1> 	; 18/11/2015
  2392                              <1> 	; 17/11/2015
  2393                              <1> 	; 16/11/2015
  2394                              <1> 	; 09/11/2015
  2395                              <1> 	; 08/11/2015
  2396                              <1> 	; 07/11/2015
  2397                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2398                              <1> 	; 01/11/2015
  2399                              <1> 	; 26/10/2015
  2400                              <1> 	; 23/10/2015
  2401 00002A43 53                  <1> 	push	ebx
  2402 00002A44 56                  <1> 	push	esi
  2403 00002A45 57                  <1> 	push	edi
  2404 00002A46 1E                  <1> 	push 	ds
  2405 00002A47 06                  <1> 	push 	es
  2406                              <1> 	; 18/11/2015
  2407 00002A48 0F20DB              <1> 	mov	ebx, cr3
  2408 00002A4B 53                  <1> 	push	ebx ; ****
  2409                              <1> 	;
  2410 00002A4C 51                  <1> 	push	ecx ; ***
  2411 00002A4D 52                  <1> 	push	edx ; **
  2412                              <1> 	;
  2413 00002A4E BB10000000          <1> 	mov	ebx, KDATA
  2414 00002A53 8EDB                <1> 	mov	ds, bx
  2415 00002A55 8EC3                <1> 	mov	es, bx
  2416                              <1> 	;
  2417 00002A57 8B0D[38610000]      <1> 	mov	ecx, [k_page_dir]
  2418 00002A5D 0F22D9              <1> 	mov	cr3, ecx
  2419                              <1> 	; 20/11/2015
  2420                              <1> 	; Interrupt identification register
  2421 00002A60 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2422                              <1> 	;
  2423 00002A64 3C08                <1> 	cmp 	al, 8 
  2424 00002A66 7702                <1> 	ja 	short com_i0
  2425                              <1> 	;
  2426                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2427                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2428                              <1> 	; 20/11/2015
  2429                              <1> 	; 17/11/2015
  2430                              <1> 	; 16/11/2015
  2431                              <1> 	; 15/11/2015
  2432                              <1> 	; 24/10/2015
  2433                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2434                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2435                              <1> 	; < serial port 1 interrupt handler >
  2436                              <1> 	;
  2437 00002A68 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2438                              <1> com_i0:
  2439                              <1> 	;push	eax ; *
  2440                              <1> 	; 07/11/2015
  2441 00002A6A A2[A6610000]        <1> 	mov 	byte [ccomport], al
  2442                              <1> 	; 09/11/2015
  2443                              <1> 	;movzx	ebx, ax ; 8 or 9
  2444                              <1> 	; 08/01/2022
  2445 00002A6F 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2446                              <1> 	; 17/11/2015
  2447                              <1>  	; reset request for response status
  2448 00002A71 88A3[9C610000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2449                              <1> 	;
  2450                              <1> 	; 20/11/2015
  2451 00002A77 EC                  <1> 	in	al, dx		; read interrupt id. register
  2452 00002A78 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2453 00002A7A 2404                <1> 	and	al, 4		; received data available?	
  2454 00002A7C 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2455                              <1> 	;
  2456                              <1> 	; 20/11/2015
  2457 00002A7E 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2458 00002A81 EC                  <1> 	in	al, dx     	; read character
  2459                              <1> 	;JMP	$+2	   	; I/O DELAY
  2460                              <1> 	; 08/11/2015
  2461                              <1> 	; 07/11/2015
  2462 00002A82 89DE                <1> 	mov	esi, ebx 
  2463 00002A84 89DF                <1> 	mov	edi, ebx
  2464 00002A86 81C6[A0610000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2465 00002A8C 81C7[A2610000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2466 00002A92 8806                <1> 	mov	[esi], al ; received char (current char)
  2467                              <1> 	; query
  2468 00002A94 20C0                <1> 	and	al, al
  2469 00002A96 7527                <1> 	jnz	short com_i2
  2470                              <1>    	; response
  2471                              <1> 	; 17/11/2015
  2472                              <1> 	; set request for response status
  2473 00002A98 FE83[9C610000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2474                              <1> 	;
  2475 00002A9E 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2476 00002AA2 EC                  <1> 	in	al, dx	   	; read line status register 
  2477 00002AA3 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2478 00002AA5 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2479 00002AA7 7445                <1> 	jz	short com_eoi 	; no
  2480 00002AA9 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2481 00002AAB 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2482 00002AAF EE                  <1> 	out	dx, al	   	; send on serial port
  2483                              <1> 	; 17/11/2015
  2484 00002AB0 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2485 00002AB3 7502                <1> 	jne 	short com_i1    ; no
  2486 00002AB5 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2487                              <1> com_i1:
  2488                              <1> 	; 17/11/2015
  2489                              <1> 	; reset request for response status (again)
  2490 00002AB7 FE8B[9C610000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2491 00002ABD EB2F                <1> 	jmp	short com_eoi
  2492                              <1> com_i2:	
  2493                              <1> 	; 08/11/2015
  2494 00002ABF 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2495 00002AC1 7417                <1> 	je	short com_i3	; (check for response signal)
  2496                              <1> 	; 07/11/2015
  2497 00002AC3 3C04                <1> 	cmp	al, 04h	; EOT
  2498 00002AC5 751C                <1> 	jne	short com_i4	
  2499                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2500                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2501                              <1> 	; 08/11/2015
  2502                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2503 00002AC7 861D[66610000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2504 00002ACD E80BFFFFFF          <1> 	call 	ctrlbrk
  2505 00002AD2 861D[66610000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2506                              <1> 	;mov	al, 04h ; EOT
  2507                              <1> 	; 08/11/2015
  2508 00002AD8 EB09                <1> 	jmp	short com_i4	
  2509                              <1> com_i3:
  2510                              <1> 	; 08/11/2015
  2511                              <1> 	; If 0FFh has been received just after a query
  2512                              <1> 	; (schar, ZERO), it is a response signal.
  2513                              <1> 	; 17/11/2015
  2514 00002ADA 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2515 00002ADD 7704                <1> 	ja	short com_i4 ; no
  2516                              <1> 	; reset query status (schar)
  2517 00002ADF 8807                <1> 	mov	[edi], al ; 0FFh
  2518 00002AE1 FEC0                <1> 	inc	al ; 0
  2519                              <1> com_i4:
  2520                              <1> 	; 27/07/2014
  2521                              <1> 	; 09/07/2014
  2522 00002AE3 D0E3                <1> 	shl	bl, 1	
  2523 00002AE5 81C3[68610000]      <1> 	add	ebx, ttychr
  2524                              <1> 	; 23/07/2014 (always overwrite)
  2525                              <1> 	;;cmp	word [ebx], 0
  2526                              <1> 	;;ja	short com_eoi
  2527                              <1> 	;
  2528 00002AEB 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2529                              <1> 			    ; scan code = 0
  2530                              <1> com_eoi:
  2531                              <1> 	;mov	al, 20h
  2532                              <1> 	;out	20h, al	   ; end of interrupt
  2533                              <1> 	;
  2534                              <1> 	; 07/11/2015
  2535                              <1>       	;pop	eax ; *
  2536 00002AEE A0[A6610000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2537                              <1> 	; al = tty number (8 or 9)
  2538 00002AF3 E8EF1A0000          <1>         call	wakeup
  2539                              <1> com_iret:
  2540                              <1> 	; 23/10/2015
  2541 00002AF8 5A                  <1> 	pop	edx ; **
  2542 00002AF9 59                  <1> 	pop	ecx ; ***
  2543                              <1> 	; 18/11/2015
  2544                              <1> 	;pop	eax ; ****
  2545                              <1> 	;mov	cr3, eax
  2546                              <1> 	;jmp	iiret
  2547 00002AFA E99CDEFFFF          <1> 	jmp	iiretp
  2548                              <1> 
  2549                              <1> ;hfgchr:
  2550                              <1> ;	db '0123456789ABCDEF?*'
  2551                              <1> ;	db 0
  2552                              <1> 
  2553                              <1> ;iiretp: ; 01/09/2015
  2554                              <1> ;	; 28/08/2015
  2555                              <1> ;	pop	eax ; (*) page directory
  2556                              <1> ;	mov	cr3, eax
  2557                              <1> ;iiret:
  2558                              <1> ;	; 22/08/2014
  2559                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2560                              <1> ;	out	20h, al	; 8259 PORT
  2561                              <1> ;	;
  2562                              <1> ;	pop	es
  2563                              <1> ;	pop	ds
  2564                              <1> ;	pop	edi
  2565                              <1> ;	pop	esi
  2566                              <1> ;	pop	ebx ; 29/08/2014
  2567                              <1> ;	pop 	eax
  2568                              <1> ;	iretd
  2569                              <1> 
  2570                              <1> sp_init:
  2571                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2572                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2573                              <1> 	; 07/11/2015
  2574                              <1> 	; 29/10/2015
  2575                              <1> 	; 26/10/2015
  2576                              <1> 	; 23/10/2015
  2577                              <1> 	; 29/06/2015
  2578                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2579                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2580                              <1> 	; Initialization of Serial Port Communication Parameters
  2581                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2582                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2583                              <1> 	;
  2584                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2585                              <1> 	;
  2586                              <1> 	; INPUT:  (29/06/2015)
  2587                              <1> 	;	AL = 0 for COM1
  2588                              <1> 	;	     1 for COM2
  2589                              <1> 	;	AH = Communication parameters	
  2590                              <1> 	;
  2591                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2592                              <1> 	;	Bit	4	3	2	1	0
  2593                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2594                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2595                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2596                              <1> 	;		11 = even
  2597                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2598                              <1> 	;		Retro UNIX 386 v1 feature only !
  2599                              <1> 	;	Bit	7    6    5  | Baud rate
  2600                              <1> 	;		------------------------
  2601                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2602                              <1> 	;		0    0    1  | 9600 (12)
  2603                              <1> 	;		0    1    0  | 19200 (6) 
  2604                              <1> 	;		0    1	  1  | 38400 (3) 
  2605                              <1> 	;		1    0	  0  | 14400 (8)
  2606                              <1> 	;		1    0	  1  | 28800 (4)
  2607                              <1> 	;		1    1    0  | 57600 (2)
  2608                              <1> 	;		1    1    1  | 115200 (1) 	
  2609                              <1> 	
  2610                              <1> 	; References:	
  2611                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2612                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2613                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2614                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2615                              <1> 	;
  2616                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2617                              <1> 	;
  2618 00002AFF BB[A2610000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2619 00002B04 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2620                              <1> 	; 29/10/2015
  2621 00002B08 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2622 00002B0C E84F000000          <1> 	call	sp_i3	; call A4	
  2623 00002B11 A880                <1> 	test	al, 80h
  2624 00002B13 740E                <1> 	jz	short sp_i0 ; OK..
  2625                              <1> 		; Error !
  2626                              <1> 	;mov	dx, 3F8h
  2627 00002B15 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2628                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2629                              <1> 	; 08/01/2022
  2630 00002B18 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2631 00002B1A E841000000          <1> 	call	sp_i3	; call A4	
  2632 00002B1F A880                <1> 	test	al, 80h
  2633 00002B21 7508                <1> 	jnz	short sp_i1
  2634                              <1> sp_i0:
  2635                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2636                              <1>         ; (INT 14h initialization code disables interrupts.)
  2637                              <1> 	;
  2638 00002B23 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2639 00002B26 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2640                              <1> sp_i1:
  2641 00002B2B 43                  <1> 	inc	ebx
  2642 00002B2C 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2643                              <1> 	; 29/10/2015
  2644                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2645                              <1> 	; 08/01/2022
  2646 00002B30 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2647 00002B32 E829000000          <1> 	call	sp_i3	; call A4	
  2648 00002B37 A880                <1> 	test	al, 80h
  2649 00002B39 740E                <1> 	jz	short sp_i2 ; OK..
  2650                              <1> 		; Error !
  2651                              <1> 	;mov	dx, 2F8h
  2652 00002B3B 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2653                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2654                              <1> 	; 08/01/2022
  2655 00002B3E B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2656 00002B40 E81B000000          <1> 	call	sp_i3	; call A4	
  2657 00002B45 A880                <1> 	test	al, 80h
  2658 00002B47 7516                <1> 	jnz	short sp_i7
  2659                              <1> sp_i2:
  2660 00002B49 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2661                              <1> sp_i6:
  2662                              <1> 	;; COM2 - enabling IRQ 3
  2663                              <1> 	; 08/01/2022
  2664 00002B4C B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2665                              <1> 	; 07/11/2015
  2666                              <1> 	; 26/10/2015
  2667                              <1> 	;pushf
  2668                              <1> 	;cli
  2669                              <1> 	;;
  2670                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2671                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2672                              <1> 	;in	al, dx 	   		; read register
  2673                              <1> 	;JMP	$+2	   		; I/O DELAY
  2674                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2675                              <1> 	;out	dx, al     		; write back to register
  2676                              <1> 	;JMP	$+2	   		; I/O DELAY
  2677                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2678                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2679                              <1> 	;in	al, dx     		; read register
  2680                              <1> 	;JMP	$+2	   		; I/O DELAY
  2681                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2682                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2683                              <1> 	;out	dx, al 	   		; write back to register
  2684                              <1> 	;JMP	$+2        		; I/O DELAY
  2685                              <1> 	;in	al, 21h    		; read interrupt mask register
  2686                              <1> 	;JMP	$+2	   		; I/O DELAY
  2687                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2688                              <1> 	;out	21h, al    		; write back to register
  2689                              <1> 	;
  2690                              <1> 	; 08/01/2022
  2691 00002B4E 9C                  <1> 	pushf
  2692 00002B4F E8AA000000          <1> 	call	sp_i8
  2693                              <1> 	; 23/10/2015
  2694 00002B54 B8[332A0000]        <1> 	mov 	eax, com2_int
  2695 00002B59 A3[E42F0000]        <1> 	mov	[com2_irq3], eax
  2696                              <1> 	; 26/10/2015
  2697 00002B5E 9D                  <1> 	popf	
  2698                              <1> sp_i7:
  2699 00002B5F C3                  <1> 	retn
  2700                              <1> 
  2701                              <1> sp_i3:
  2702                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2703                              <1> 	; 28/10/2015
  2704 00002B60 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2705 00002B62 B000                <1> 	mov	al, 0
  2706 00002B64 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2707 00002B65 EB00                <1> 	JMP	$+2			; I/O DELAY
  2708 00002B67 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2709 00002B6A B080                <1> 	mov	al, 80h			
  2710 00002B6C EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2711                              <1> 	;-----	SET BAUD RATE DIVISOR
  2712                              <1> 	; 26/10/2015
  2713 00002B6D 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2714                              <1> 					; of the divisor value
  2715 00002B70 88C8                <1> 	mov	al, cl	; 1
  2716 00002B72 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2717                              <1> 					; 2 = 57600 baud
  2718                              <1> 					; 3 = 38400 baud
  2719                              <1> 					; 6 = 19200 baud
  2720                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2721 00002B73 EB00                <1> 	JMP	$+2			; I/O DELAY
  2722 00002B75 28C0                <1> 	sub	al, al
  2723 00002B77 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2724                              <1> 					; of the divisor value
  2725 00002B79 EE                  <1> 	out	dx, al ; 0
  2726 00002B7A EB00                <1> 	JMP	$+2			; I/O DELAY
  2727                              <1> 	;	
  2728 00002B7C 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2729                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2730 00002B7E 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2731 00002B81 EE                  <1> 	out	dx, al			
  2732 00002B82 EB00                <1> 	JMP	$+2			; I/O DELAY
  2733                              <1> 	; 29/10/2015
  2734 00002B84 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2735 00002B86 30C0                <1> 	xor	al, al			; 0
  2736 00002B88 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2737 00002B89 EB00                <1> 	JMP	$+2	
  2738                              <1> sp_i4:
  2739                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2740                              <1> 	; 29/06/2015 (line status after modem status)
  2741 00002B8B 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2742                              <1> sp_i4s:
  2743 00002B8E EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2744 00002B8F EB00                <1> 	JMP	$+2			; I/O DELAY
  2745 00002B91 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2746 00002B93 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2747                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2748 00002B95 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2749                              <1> 	; AL = Line status, AH = Modem status
  2750 00002B96 C3                  <1> 	retn
  2751                              <1> 
  2752                              <1> sp_status:
  2753                              <1> 	; 29/06/2015
  2754                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2755                              <1> 	; Get serial port status
  2756 00002B97 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2757 00002B9B 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2758                              <1> 					; dx = 2FEh for COM2
  2759 00002B9D EBEF                <1> 	jmp	short sp_i4s
  2760                              <1> 
  2761                              <1> sp_setp: ; Set serial port communication parameters
  2762                              <1> 	; 04/02/2022 
  2763                              <1> 	;	(Retro UNIX 386 v1, Kernel v0.2.0.18)
  2764                              <1> 	; 08/01/2022
  2765                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2766                              <1> 	; 07/11/2015
  2767                              <1> 	; 29/10/2015
  2768                              <1> 	; 29/06/2015
  2769                              <1> 	; Retro UNIX 386 v1 feature only !	
  2770                              <1> 	;
  2771                              <1> 	; INPUT:
  2772                              <1> 	;	AL = 0 for COM1
  2773                              <1> 	;	     1 for COM2
  2774                              <1> 	;	AH = Communication parameters (*)
  2775                              <1> 	; OUTPUT:
  2776                              <1> 	;	CL = Line status
  2777                              <1> 	;	CH = Modem status
  2778                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2779                              <1> 	;		 'invalid parameter !' 
  2780                              <1> 	;		 	 or
  2781                              <1> 	;		 'device not ready !' error
  2782                              <1> 	;	
  2783                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2784                              <1> 	;	Bit	4	3	2	1	0
  2785                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2786                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2787                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2788                              <1> 	;		11 = even
  2789                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2790                              <1> 	;		Retro UNIX 386 v1 feature only !
  2791                              <1> 	;	Bit	7    6    5  | Baud rate
  2792                              <1> 	;		------------------------
  2793                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2794                              <1> 	;		0    0    1  | 9600 (12)
  2795                              <1> 	;		0    1    0  | 19200 (6) 
  2796                              <1> 	;		0    1	  1  | 38400 (3) 
  2797                              <1> 	;		1    0	  0  | 14400 (8)
  2798                              <1> 	;		1    0	  1  | 28800 (4)
  2799                              <1> 	;		1    1    0  | 57600 (2)
  2800                              <1> 	;		1    1    1  | 115200 (1) 
  2801                              <1> 	;
  2802                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2803                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2804                              <1> 	;
  2805                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2806                              <1> 	;
  2807 00002B9F 66BAF803            <1> 	mov	dx, 3F8h
  2808 00002BA3 BB[A2610000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2809 00002BA8 3C01                <1> 	cmp	al, 1
  2810 00002BAA 7770                <1> 	ja 	short sp_invp_err
  2811 00002BAC 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2812 00002BAE FECE                <1> 	dec	dh ; 2F8h
  2813 00002BB0 43                  <1> 	inc	ebx ; COM2 control byte offset
  2814                              <1> sp_setp1:
  2815                              <1> 	; 29/10/2015
  2816 00002BB1 8823                <1> 	mov	[ebx], ah
  2817 00002BB3 0FB6CC              <1> 	movzx 	ecx, ah
  2818 00002BB6 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2819 00002BB9 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2820 00002BBC 8A81[2B2C0000]      <1> 	mov	al, [ecx+b_div_tbl]
  2821 00002BC2 6689C1              <1> 	mov	cx, ax
  2822 00002BC5 E896FFFFFF          <1> 	call	sp_i3
  2823 00002BCA 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2824 00002BCD A880                <1> 	test	al, 80h
  2825 00002BCF 740F                <1> 	jz	short sp_setp2
  2826 00002BD1 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2827                              <1> stp_dnr_err:
  2828 00002BD4 C705[4F650000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2828 00002BDC 0000                <1>
  2829                              <1> 	; CL = Line status, CH = Modem status
  2830 00002BDE F9                  <1> 	stc
  2831 00002BDF C3                  <1> 	retn
  2832                              <1> sp_setp2:
  2833 00002BE0 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2834                              <1>         ;jna	sp_i6
  2835                              <1> 		      ; COM1 (3F?h)
  2836                              <1> 	; 24/12/2021
  2837 00002BE3 7705                <1> 	ja	short sp_i5
  2838 00002BE5 E962FFFFFF          <1> 	jmp	sp_i6
  2839                              <1> sp_i5: 
  2840                              <1> 	; 08/01/2022
  2841 00002BEA B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2842                              <1> 	; 07/11/2015
  2843                              <1> 	; 26/10/2015
  2844                              <1> 	; 29/06/2015
  2845                              <1> 	;
  2846                              <1> 	;; COM1 - enabling IRQ 4
  2847                              <1> 	;pushf
  2848                              <1> 	;cli
  2849                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2850                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2851                              <1> 	;in	al, dx 	   		; read register
  2852                              <1> 	;JMP	$+2			; I/O DELAY
  2853                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2854                              <1> 	;out	dx, al     		; write back to register
  2855                              <1> 	;JMP	$+2			; I/O DELAY
  2856                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2857                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2858                              <1> 	;in	al, dx     		; read register
  2859                              <1> 	;JMP	$+2			; I/O DELAY
  2860                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2861                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2862                              <1> 	;out	dx, al 	   		; write back to register
  2863                              <1> 	;JMP	$+2        		; I/O DELAY
  2864                              <1> 	;in	al, 21h    		; read interrupt mask register
  2865                              <1> 	;JMP	$+2			; I/O DELAY
  2866                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2867                              <1> 	;out	21h, al    		; write back to register
  2868                              <1> 	;
  2869                              <1> 	; 08/01/2022
  2870 00002BEC 9C                  <1> 	pushf
  2871 00002BED E80C000000          <1> 	call	sp_i8
  2872                              <1> 	; 23/10/2015
  2873 00002BF2 B8[3C2A0000]        <1> 	mov 	eax, com1_int
  2874 00002BF7 A3[E02F0000]        <1> 	mov	[com1_irq4], eax
  2875                              <1> 	; 26/10/2015
  2876 00002BFC 9D                  <1> 	popf
  2877 00002BFD C3                  <1> 	retn
  2878                              <1> 
  2879                              <1> sp_i8:
  2880                              <1> 	; 08/01/2022
  2881                              <1> 	;pushf
  2882 00002BFE FA                  <1> 	cli
  2883                              <1> 	;
  2884                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2885 00002BFF B2FC                <1> 	mov	dl, 0FCh
  2886 00002C01 EC                  <1> 	in	al, dx 	   		; read register
  2887 00002C02 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2888 00002C04 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2889 00002C06 EE                  <1> 	out	dx, al     		; write back to register
  2890 00002C07 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2891                              <1> 	;mov	dx, 2F9h  ; 3F9h 		; interrupt enable register
  2892 00002C09 B2F9                <1> 	mov	dl, 0F9h
  2893 00002C0B EC                  <1> 	in	al, dx     		; read register
  2894 00002C0C EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2895                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2896 00002C0E 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2897 00002C10 EE                  <1> 	out	dx, al 	   		; write back to register
  2898 00002C11 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2899 00002C13 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2900 00002C15 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2901                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2902 00002C17 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2903 00002C19 E621                <1> 	out	21h, al    		; write back to register
  2904                              <1> 	;
  2905                              <1> 	;popf	
  2906 00002C1B C3                  <1> 	retn
  2907                              <1> 
  2908                              <1> sp_invp_err:
  2909 00002C1C C705[4F650000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2909 00002C24 0000                <1>
  2910 00002C26 31C9                <1> 	xor	ecx, ecx
  2911 00002C28 49                  <1> 	dec	ecx ; 0FFFFh
  2912 00002C29 F9                  <1> 	stc
  2913 00002C2A C3                  <1> 	retn
  2914                              <1> 
  2915                              <1> ; 29/10/2015
  2916                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2917 00002C2B 010C0603080401      <1> 	db 1, 12, 6, 3, 8, 4, 1
  2918                              <1> 
  2919                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2920                              <1> epoch:
  2921                              <1> 	; 17/07/2022
  2922                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2923                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2924                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2925                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2926                              <1> 	; 'epoch' procedure prototype: 
  2927                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2928                              <1> 	; 14/11/2012
  2929                              <1> 	; unixboot.asm (boot file configuration)
  2930                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2931                              <1> 	; 21/7/2012
  2932                              <1> 	; 15/7/2012
  2933                              <1> 	; 14/7/2012		
  2934                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2935                              <1> 	; compute current date and time as UNIX Epoch/Time
  2936                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2937                              <1> 	;
  2938                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2939                              <1> 	;
  2940 00002C32 E818010000          <1> 	call 	get_rtc_time		; Return Current Time
  2941 00002C37 86E9                <1>         xchg 	ch,cl
  2942 00002C39 66890D[A65E0000]    <1>         mov 	[hour], cx
  2943 00002C40 86F2                <1>         xchg 	dh,dl
  2944 00002C42 668915[A85E0000]    <1>         mov 	[second], dx
  2945                              <1> 	;
  2946 00002C49 E832010000          <1>         call 	get_rtc_date		; Return Current Date
  2947 00002C4E 86E9                <1>         xchg 	ch,cl
  2948 00002C50 66890D[A25E0000]    <1>         mov 	[year], cx
  2949 00002C57 86F2                <1>         xchg 	dh,dl
  2950 00002C59 668915[A45E0000]    <1>         mov 	[month], dx
  2951                              <1> 	;
  2952 00002C60 66B93030            <1> 	mov 	cx, 3030h
  2953                              <1> 	;
  2954 00002C64 A0[A65E0000]        <1> 	mov 	al, [hour] ; Hour
  2955                              <1>         	; AL <= BCD number)
  2956 00002C69 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2957                              <1> 					; AH = AL / 10h
  2958                              <1> 					; AL = AL MOD 10h
  2959 00002C6B D50A                <1>         aad 	; AX= AH*10+AL
  2960 00002C6D A2[A65E0000]        <1> 	mov 	[hour], al
  2961 00002C72 A0[A75E0000]        <1> 	mov 	al, [hour+1] ; Minute
  2962                              <1>         	; AL <= BCD number)
  2963 00002C77 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2964                              <1> 					; AH = AL / 10h
  2965                              <1> 					; AL = AL MOD 10h
  2966 00002C79 D50A                <1>         aad 	; AX= AH*10+AL
  2967 00002C7B A2[A75E0000]        <1> 	mov 	[minute], al
  2968 00002C80 A0[A85E0000]        <1> 	mov 	al, [second] ; Second
  2969                              <1>         	; AL <= BCD number)
  2970 00002C85 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2971                              <1> 					; AH = AL / 10h
  2972                              <1> 					; AL = AL MOD 10h
  2973 00002C87 D50A                <1>         aad 	; AX= AH*10+AL
  2974 00002C89 A2[A85E0000]        <1> 	mov 	[second], al
  2975 00002C8E 66A1[A25E0000]      <1> 	mov 	ax, [year] ; Year (century)
  2976                              <1>  	;push 	ax
  2977                              <1> 	; 08/01/2022
  2978 00002C94 50                  <1> 	push	eax
  2979                              <1> 	   	; AL <= BCD number)
  2980 00002C95 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2981                              <1> 					; AH = AL / 10h
  2982                              <1> 					; AL = AL MOD 10h
  2983 00002C97 D50A                <1>         aad 	; AX= AH*10+AL
  2984 00002C99 B464                <1> 	mov 	ah, 100
  2985 00002C9B F6E4                <1> 	mul 	ah
  2986 00002C9D 66A3[A25E0000]      <1> 	mov 	[year], ax
  2987                              <1> 	;pop	ax
  2988                              <1> 	; 08/01/2022
  2989 00002CA3 58                  <1> 	pop	eax
  2990 00002CA4 88E0                <1> 	mov	al, ah
  2991                              <1>         	; AL <= BCD number)
  2992 00002CA6 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2993                              <1> 					; AH = AL / 10h
  2994                              <1> 					; AL = AL MOD 10h
  2995 00002CA8 D50A                <1>         aad 	; AX= AH*10+AL
  2996 00002CAA 660105[A25E0000]    <1> 	add 	[year], ax
  2997 00002CB1 A0[A45E0000]        <1> 	mov 	al, [month] ; Month
  2998                              <1>            	; AL <= BCD number)
  2999 00002CB6 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3000                              <1> 					; AH = AL / 10h
  3001                              <1> 					; AL = AL MOD 10h
  3002 00002CB8 D50A                <1>         aad 	; AX= AH*10+AL
  3003 00002CBA A2[A45E0000]        <1> 	mov 	[month], al	
  3004 00002CBF A0[A55E0000]        <1>         mov     al, [month+1]      	; Day
  3005                              <1>            	; AL <= BCD number)
  3006 00002CC4 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3007                              <1> 					; AH = AL / 10h
  3008                              <1> 					; AL = AL MOD 10h
  3009 00002CC6 D50A                <1>         aad 	; AX= AH*10+AL
  3010 00002CC8 A2[A55E0000]        <1>         mov     [day], al
  3011                              <1> 	
  3012                              <1> convert_to_epoch:
  3013                              <1> 	; 17/07/2022
  3014                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3015                              <1> 	; 09/04/2013 (retro UNIX 8086 v1)
  3016                              <1> 	;
  3017                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3018                              <1> 	;
  3019                              <1> 	; Derived from DALLAS Semiconductor
  3020                              <1> 	; Application Note 31 (DS1602/DS1603)
  3021                              <1> 	; 6 May 1998
  3022 00002CCD 29C0                <1> 	sub 	eax, eax
  3023 00002CCF 66A1[A25E0000]      <1> 	mov 	ax, [year]
  3024 00002CD5 662DB207            <1> 	sub 	ax, 1970
  3025 00002CD9 BA6D010000          <1> 	mov 	edx, 365
  3026 00002CDE F7E2                <1> 	mul 	edx
  3027 00002CE0 31DB                <1> 	xor 	ebx, ebx
  3028 00002CE2 8A1D[A45E0000]      <1> 	mov 	bl, [month]
  3029 00002CE8 FECB                <1> 	dec 	bl
  3030 00002CEA D0E3                <1> 	shl 	bl, 1
  3031                              <1> 	;sub	edx, edx
  3032 00002CEC 668B93[AA5E0000]    <1> 	mov 	dx, [EBX+DMonth]
  3033 00002CF3 8A1D[A55E0000]      <1>         mov     bl, [day]
  3034 00002CF9 FECB                <1> 	dec 	bl
  3035 00002CFB 01D0                <1> 	add 	eax, edx
  3036 00002CFD 01D8                <1> 	add 	eax, ebx
  3037                              <1> 			; EAX = days since 1/1/1970
  3038 00002CFF 668B15[A25E0000]    <1> 	mov 	dx, [year]
  3039 00002D06 6681EAB107          <1> 	sub 	dx, 1969
  3040                              <1> 	;shr 	dx, 1
  3041                              <1> 	;shr 	dx, 1		
  3042                              <1> 	; 17/07/2022
  3043 00002D0B C1EA02              <1> 	shr	edx, 2
  3044                              <1> 		; (year-1969)/4
  3045 00002D0E 01D0                <1> 	add 	eax, edx
  3046                              <1> 			; + leap days since 1/1/1970
  3047 00002D10 803D[A45E0000]02    <1> 	cmp 	byte [month], 2	; if past february
  3048 00002D17 7610                <1> 	jna 	short cte1
  3049 00002D19 668B15[A25E0000]    <1> 	mov 	dx, [year]
  3050 00002D20 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3051 00002D24 7503                <1> 	jnz 	short cte1		
  3052                              <1> 			; and if leap year
  3053 00002D26 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3054                              <1> cte1: 			; compute seconds since 1/1/1970
  3055 00002D29 BA18000000          <1> 	mov 	edx, 24
  3056 00002D2E F7E2                <1> 	mul	edx
  3057 00002D30 8A15[A65E0000]      <1> 	mov 	dl, [hour]
  3058 00002D36 01D0                <1> 	add 	eax, edx
  3059                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3060                              <1> 	;mov	ebx, 60
  3061 00002D38 B33C                <1> 	mov	bl, 60
  3062 00002D3A F7E3                <1> 	mul	ebx
  3063 00002D3C 8A15[A75E0000]      <1> 	mov 	dl, [minute]
  3064 00002D42 01D0                <1> 	add 	eax, edx
  3065                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3066                              <1> 	;mov 	ebx, 60
  3067 00002D44 F7E3                <1> 	mul	ebx
  3068 00002D46 8A15[A85E0000]      <1> 	mov 	dl, [second]
  3069 00002D4C 01D0                <1> 	add 	eax, edx
  3070                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3071 00002D4E C3                  <1> 	retn
  3072                              <1> 
  3073                              <1> get_rtc_time:
  3074                              <1> 	; 15/03/2015
  3075                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	:
  3076                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	:
  3077                              <1> 	; INT 1Ah						:
  3078                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3079                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3080                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3081                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3082                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3083                              <1> 	;								
  3084                              <1> RTC_20: 			; GET RTC TIME
  3085 00002D4F FA                  <1> 	cli
  3086 00002D50 E8E4DDFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3087 00002D55 7227                <1> 	JC	short RTC_29	; EXIT IF ERROR (CY= 1)
  3088                              <1> 
  3089 00002D57 B000                <1> 	MOV	AL,CMOS_SECONDS ; SET ADDRESS OF SECONDS
  3090 00002D59 E8C3DDFFFF          <1> 	CALL	CMOS_READ	; GET SECONDS
  3091 00002D5E 88C6                <1> 	MOV	DH,AL		; SAVE
  3092 00002D60 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3093 00002D62 E8BADDFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3094 00002D67 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3095 00002D69 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3096 00002D6B B002                <1> 	MOV	AL,CMOS_MINUTES ; SET ADDRESS OF MINUTES
  3097 00002D6D E8AFDDFFFF          <1> 	CALL	CMOS_READ	; GET MINUTES
  3098 00002D72 88C1                <1> 	MOV	CL,AL		; SAVE
  3099 00002D74 B004                <1> 	MOV	AL,CMOS_HOURS	; SET ADDRESS OF HOURS
  3100 00002D76 E8A6DDFFFF          <1> 	CALL	CMOS_READ	; GET HOURS
  3101 00002D7B 88C5                <1> 	MOV	CH,AL		; SAVE
  3102 00002D7D F8                  <1> 	CLC			; SET CY= 0
  3103                              <1> RTC_29:
  3104 00002D7E FB                  <1> 	sti
  3105 00002D7F C3                  <1> 	RETn			; RETURN WITH RESULT IN CARRY FLAG
  3106                              <1> 
  3107                              <1> get_rtc_date:
  3108                              <1> 	; 15/03/2015
  3109                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	       :
  3110                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	       :
  3111                              <1> 	; INT 1Ah						       :
  3112                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3113                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3114                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3115                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3116                              <1> 	;      (DL) = DAY IN BCD (01-31).			       :		
  3117                              <1> 	;
  3118                              <1> RTC_40: 			; GET RTC DATE
  3119 00002D80 FA                  <1> 	cli
  3120 00002D81 E8B3DDFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3121 00002D86 7225                <1> 	JC	short RTC_49	; EXIT IF ERROR (CY= 1)
  3122                              <1> 
  3123 00002D88 B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH
  3124 00002D8A E892DDFFFF          <1> 	CALL	CMOS_READ	; READ DAY OF MONTH
  3125 00002D8F 88C2                <1> 	MOV	DL,AL		; SAVE
  3126 00002D91 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH
  3127 00002D93 E889DDFFFF          <1> 	CALL	CMOS_READ	; READ MONTH
  3128 00002D98 88C6                <1> 	MOV	DH,AL		; SAVE
  3129 00002D9A B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR
  3130 00002D9C E880DDFFFF          <1> 	CALL	CMOS_READ	; READ YEAR
  3131 00002DA1 88C1                <1> 	MOV	CL,AL		; SAVE
  3132 00002DA3 B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY LOCATION
  3133 00002DA5 E877DDFFFF          <1> 	CALL	CMOS_READ	; GET CENTURY BYTE
  3134 00002DAA 88C5                <1> 	MOV	CH,AL		; SAVE
  3135 00002DAC F8                  <1> 	CLC			; SET CY=0
  3136                              <1> RTC_49:
  3137 00002DAD FB                  <1> 	sti
  3138 00002DAE C3                  <1> 	RETn			; RETURN WITH RESULTS IN CARRY FLAG
  3139                              <1> 
  3140                              <1> set_date_time:
  3141                              <1> convert_from_epoch:
  3142                              <1> 	; 02/06/2022
  3143                              <1> 	; 01/06/2022 (BugFix)
  3144                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3145                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3146                              <1> 	; 'convert_from_epoch' procedure prototype:
  3147                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3148                              <1> 	;
  3149                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))
  3150                              <1> 	;
  3151                              <1> 	; Derived from DALLAS Semiconductor
  3152                              <1> 	; Application Note 31 (DS1602/DS1603)
  3153                              <1> 	; 6 May 1998
  3154                              <1> 	;
  3155                              <1> 	; INPUT:
  3156                              <1> 	; EAX = Unix (Epoch) Time
  3157                              <1> 	;
  3158 00002DAF 31D2                <1> 	xor 	edx, edx
  3159                              <1> 	; 02/06/2022
  3160 00002DB1 31C9                <1> 	xor	ecx, ecx
  3161 00002DB3 31DB                <1> 	xor	ebx, ebx
  3162                              <1> 	;mov 	ecx, 60
  3163 00002DB5 B13C                <1> 	mov	cl, 60
  3164 00002DB7 F7F1                <1> 	div	ecx
  3165                              <1> 	;mov 	[imin], eax  ; whole minutes
  3166                              <1> 			     ; since 1/1/1970
  3167                              <1> 	;mov 	[second], dx ; leftover seconds
  3168 00002DB9 8815[A85E0000]      <1> 	mov	[second], dl ; 02/06/2022
  3169 00002DBF 29D2                <1> 	sub 	edx, edx
  3170 00002DC1 F7F1                <1> 	div	ecx
  3171                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3172                              <1> 	;		     ; since 1/1/1970
  3173                              <1> 	;mov 	[minute], dx ; leftover minutes
  3174 00002DC3 8815[A75E0000]      <1> 	mov	[minute], dl ; 02/06/2022
  3175 00002DC9 31D2                <1> 	xor	edx, edx
  3176                              <1> 	;mov 	cx, 24
  3177 00002DCB B118                <1> 	mov 	cl, 24
  3178 00002DCD F7F1                <1> 	div	ecx
  3179                              <1> 	;mov 	[iday], ax   ; whole days
  3180                              <1> 			     ; since 1/1/1970
  3181                              <1> 	;mov 	[hour], dx   ; leftover hours
  3182 00002DCF 8815[A65E0000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3183                              <1> 
  3184 00002DD5 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3185                              <1> 			     ; 1/1/1968 	
  3186                              <1> 	;mov 	[iday], ax
  3187 00002DDA 50                  <1> 	push 	eax
  3188 00002DDB 29D2                <1> 	sub	edx, edx
  3189 00002DDD B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3190 00002DE2 F7F1                <1> 	div	ecx
  3191 00002DE4 59                  <1> 	pop 	ecx
  3192                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3193                              <1> 	;push	dx
  3194                              <1> 	; 01/06/2022
  3195 00002DE5 52                  <1> 	push 	edx
  3196                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3197 00002DE6 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3198 00002DEA F5                  <1> 	cmc		     ; add this quadyr's leap day
  3199 00002DEB 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3200                              <1> 	;mov 	[lday], ax   ; since 1968
  3201                              <1> 	;mov 	cx, [iday]
  3202 00002DEE 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday
  3203 00002DEF 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3204 00002DF1 B96D010000          <1> 	mov 	ecx, 365
  3205 00002DF6 31D2                <1> 	xor	edx, edx
  3206                              <1> 	; EAX = iday-lday, EDX = 0
  3207 00002DF8 F7F1                <1> 	div	ecx
  3208                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3209                              <1> 	;jday = iday - (iyrs*365) - lday
  3210                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3211                              <1> 	;add	eax, 1968
  3212 00002DFA 6605B007            <1> 	add 	ax, 1968     ; compute year
  3213 00002DFE 66A3[A25E0000]      <1> 	mov 	[year], ax
  3214                              <1> 	;mov 	cx, dx
  3215                              <1> 	; 02/06/2022
  3216 00002E04 89D1                <1> 	mov	ecx, edx
  3217                              <1> 	;mov 	dx, [qday]
  3218                              <1> 	;pop	dx
  3219                              <1> 	; 01/06/2022
  3220 00002E06 5A                  <1> 	pop 	edx
  3221 00002E07 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3222 00002E0C 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3223 00002E0E 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3224 00002E12 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3225 00002E13 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3226                              <1> cfe1:			
  3227                              <1> 	;mov 	[jday], cx
  3228                              <1> 	;mov 	bx, 12       ; estimate month
  3229                              <1> 	;sub	ebx, ebx
  3230                              <1> 	; 02/06/2022
  3231 00002E17 B30C                <1> 	mov	bl, 12
  3232 00002E19 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3233 00002E1D 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3234                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3235                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3236                              <1> 	; 02/06/2022
  3237 00002E21 39D1                <1> 	cmp	ecx, edx 	 		
  3238 00002E23 7319                <1> 	jnb 	short cfe3
  3239                              <1> 	;dec 	bx           ; month = month - 1
  3240 00002E25 FECB                <1> 	dec	bl			
  3241                              <1> 	;shl 	bx, 1
  3242 00002E27 D0E3                <1> 	shl	bl, 1
  3243 00002E29 668B93[AA5E0000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3244                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3245                              <1> 	; 02/06/2022
  3246 00002E30 D0EB                <1> 	shr	bl, 1
  3247 00002E32 80FB01              <1> 	cmp	bl, 1
  3248                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0
  3249 00002E35 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3250 00002E37 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3251 00002E39 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3252                              <1> 	;inc 	dx           ; mday = mday + 1
  3253 00002E3B 42                  <1> 	inc	edx
  3254 00002E3C EBE3                <1> 	jmp 	short cfe2
  3255                              <1> cfe3:
  3256                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3257                              <1> 	; 02/06/2022
  3258 00002E3E FEC3                <1> 	inc	bl
  3259                              <1> 	;mov 	[month], bx
  3260 00002E40 881D[A45E0000]      <1> 	mov	[month], bl
  3261                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1
  3262 00002E46 29D1                <1> 	sub	ecx, edx
  3263                              <1> 	;inc 	cx
  3264 00002E48 FEC1                <1> 	inc	cl
  3265                              <1> 	;mov 	[day], cx
  3266 00002E4A 880D[A55E0000]      <1> 	mov	[day], cl    ; 02/06/2022
  3267                              <1> 	
  3268                              <1> 	; eax, ebx, ecx, edx is changed at return
  3269                              <1> 	; output ->
  3270                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3271                              <1> 	
  3272                              <1> 	; 01/06/2022 (BugFix)
  3273                              <1> _set_date:
  3274 00002E50 66A1[A25E0000]      <1> 	mov	ax, [year]
  3275 00002E56 B520                <1> 	mov	ch, 20h ; century (bcd)
  3276 00002E58 662DD007            <1> 	sub	ax, 2000
  3277 00002E5C 7306                <1> 	jnc	short set_date
  3278 00002E5E B519                <1> 	mov	ch, 19h ; century (bcd) 
  3279 00002E60 6683C064            <1> 	add	ax, 100	
  3280                              <1> 	; 01/06/2022
  3281                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3282                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3283                              <1> set_date:
  3284                              <1>         ;mov	al, [year+1]
  3285                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3286                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3287                              <1> 	;		     ; AL = AH * 10h + AL
  3288                              <1> 	;mov 	ch, al ; century (BCD)
  3289                              <1> 	;mov 	al, [year]
  3290                              <1> 	; al = year (0-99) ; 01/06/2022
  3291 00002E64 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3292 00002E66 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3293                              <1> 			     ; AL = AH * 10h + AL
  3294 00002E68 88C1                <1> 	mov 	cl, al ; year (BCD)
  3295 00002E6A A0[A45E0000]        <1>         mov 	al, [month]
  3296 00002E6F D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3297 00002E71 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3298                              <1> 			     ; AL = AH * 10h + AL
  3299 00002E73 88C6                <1> 	mov 	dh, al ; month (BCD)
  3300 00002E75 A0[A55E0000]        <1> 	mov 	al, [day]
  3301 00002E7A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3302 00002E7C D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3303                              <1> 			     ; AL = AH * 10h + AL
  3304                              <1> 	; 01/06/2022 (BugFix)
  3305 00002E7E 88C2                <1> 	mov 	dl, al ; day (BCD)
  3306                              <1> 
  3307                              <1> 	; Set real-time clock date
  3308 00002E80 E879000000          <1> 	call	set_rtc_date
  3309                              <1> set_time:
  3310                              <1>         ; Read real-time clock time 
  3311                              <1> 	; (get day light saving time bit status)
  3312 00002E85 FA                  <1>  	cli
  3313 00002E86 E8AEDCFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3314                              <1> 	; cf = 1 -> al = 0
  3315 00002E8B 7207                <1>         jc      short stime1
  3316 00002E8D B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3317 00002E8F E88DDCFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3318                              <1> stime1:
  3319 00002E94 FB                  <1> 	sti
  3320 00002E95 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3321 00002E97 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3322                              <1> 	; DL = 1 or 0 (day light saving time)
  3323                              <1> 	;	
  3324 00002E99 A0[A65E0000]        <1> 	mov 	al, [hour]
  3325 00002E9E D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3326 00002EA0 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3327                              <1> 			     ; AL = AH * 10h + AL
  3328 00002EA2 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3329 00002EA4 A0[A75E0000]        <1>         mov     al, [minute]
  3330 00002EA9 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3331 00002EAB D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3332                              <1> 			     ; AL = AH * 10h + AL
  3333 00002EAD 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3334 00002EAF A0[A85E0000]        <1>         mov     al, [second]
  3335 00002EB4 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3336 00002EB6 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3337                              <1> 			     ; AL = AH * 10h + AL
  3338 00002EB8 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3339                              <1> 
  3340                              <1> 	; Set real-time clock time
  3341                              <1>  	; call	set_rtc_time
  3342                              <1> set_rtc_time:
  3343                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)		  :
  3344                              <1> 	; 15/03/2015							  :
  3345                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code		  :
  3346                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES		  :
  3347                              <1> 	; INT 1Ah							  :
  3348                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			  :
  3349                              <1> 	;      (CH) = HOURS IN BCD (00-23)			          :
  3350                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			          :
  3351                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			          :
  3352                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.      :
  3353                              <1> 	;								  :
  3354                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3355                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3356                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3357                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3358                              <1> 	;								  :
  3359                              <1> RTC_30: 			; SET RTC TIME
  3360 00002EBA FA                  <1> 	cli
  3361 00002EBB E879DCFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3362 00002EC0 7305                <1> 	JNC	short RTC_35	; GO AROUND IF CLOCK OPERATING
  3363 00002EC2 E886000000          <1> 	CALL	RTC_STA 	; ELSE TRY INITIALIZING CLOCK
  3364                              <1> RTC_35:
  3365 00002EC7 88F4                <1> 	MOV	AH,DH		; GET TIME BYTE - SECONDS
  3366 00002EC9 B000                <1> 	MOV	AL,CMOS_SECONDS ; ADDRESS SECONDS
  3367 00002ECB E89D000000          <1> 	CALL	CMOS_WRITE	; UPDATE SECONDS
  3368 00002ED0 88CC                <1> 	MOV	AH,CL		; GET TIME BYTE - MINUTES
  3369 00002ED2 B002                <1> 	MOV	AL,CMOS_MINUTES ; ADDRESS MINUTES
  3370 00002ED4 E894000000          <1> 	CALL	CMOS_WRITE	; UPDATE MINUTES
  3371 00002ED9 88EC                <1> 	MOV	AH,CH		; GET TIME BYTE - HOURS
  3372 00002EDB B004                <1> 	MOV	AL,CMOS_HOURS	; ADDRESS HOURS
  3373 00002EDD E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3374                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3375 00002EE2 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3376 00002EE6 E836DCFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT TIME
  3377 00002EEB 2462                <1> 	AND	AL,01100010B	; MASK FOR VALID BIT POSITIONS
  3378 00002EED 0C02                <1> 	OR	AL,00000010B	; TURN ON 24 HOUR MODE
  3379 00002EEF 80E201              <1> 	AND	DL,00000001B	; USE ONLY THE DSE BIT
  3380 00002EF2 08D0                <1> 	OR	AL,DL		; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3381 00002EF4 86E0                <1> 	XCHG	AH,AL		; PLACE IN WORK REGISTER AND GET ADDRESS
  3382 00002EF6 E872000000          <1> 	CALL	CMOS_WRITE	; SET NEW ALARM BITS
  3383 00002EFB F8                  <1> 	CLC			; SET CY= 0
  3384 00002EFC FB                  <1> 	sti
  3385 00002EFD C3                  <1> 	RETn			; RETURN WITH CY= 0
  3386                              <1> 
  3387                              <1> set_rtc_date:
  3388                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)	   :
  3389                              <1> 	; 15/03/2015						   :
  3390                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	   :
  3391                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	   :
  3392                              <1> 	; INT 1Ah						   :
  3393                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3394                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3395                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3396                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3397                              <1> 	;     (DL) = DAY IN BCD (01-31).			   :
  3398                              <1> 	;							   :
  3399                              <1> RTC_50: 			; SET RTC DATE
  3400 00002EFE FA                  <1> 	cli
  3401 00002EFF E835DCFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3402 00002F04 7305                <1> 	JNC	short RTC_55	; GO AROUND IF NO ERROR
  3403 00002F06 E842000000          <1> 	CALL	RTC_STA 	; ELSE INITIALIZE CLOCK
  3404                              <1> RTC_55:
  3405 00002F0B 66B80600            <1> 	MOV	AX,CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE
  3406 00002F0F E859000000          <1> 	CALL	CMOS_WRITE	; LOAD ZEROS TO DAY OF WEEK
  3407 00002F14 88D4                <1> 	MOV	AH,DL		; GET DAY OF MONTH BYTE
  3408 00002F16 B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE
  3409 00002F18 E850000000          <1> 	CALL	CMOS_WRITE	; WRITE OF DAY OF MONTH REGISTER
  3410 00002F1D 88F4                <1> 	MOV	AH,DH		; GET MONTH
  3411 00002F1F B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH BYTE
  3412 00002F21 E847000000          <1> 	CALL	CMOS_WRITE	; WRITE MONTH REGISTER
  3413 00002F26 88CC                <1> 	MOV	AH,CL		; GET YEAR BYTE
  3414 00002F28 B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR REGISTER
  3415 00002F2A E83E000000          <1> 	CALL	CMOS_WRITE	; WRITE YEAR REGISTER
  3416 00002F2F 88EC                <1> 	MOV	AH,CH		; GET CENTURY BYTE
  3417 00002F31 B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY BYTE
  3418 00002F33 E835000000          <1> 	CALL	CMOS_WRITE	; WRITE CENTURY LOCATION
  3419                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3420 00002F38 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3421 00002F3C E8E0DBFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT SETTINGS
  3422 00002F41 247F                <1> 	AND	AL,07FH 	; CLEAR 'SET BIT'
  3423 00002F43 86E0                <1> 	XCHG	AH,AL		; MOVE TO WORK REGISTER
  3424 00002F45 E823000000          <1> 	CALL	CMOS_WRITE	; AND START CLOCK UPDATING
  3425 00002F4A F8                  <1> 	CLC			; SET CY= 0
  3426 00002F4B FB                  <1> 	sti
  3427 00002F4C C3                  <1> 	RETn			; RETURN CY=0
  3428                              <1> 
  3429                              <1> 	; 15/03/2015
  3430                              <1> RTC_STA:			; INITIALIZE REAL TIME CLOCK
  3431 00002F4D B426                <1> 	mov	ah, 26h
  3432 00002F4F B00A                <1> 	mov	al, CMOS_REG_A	; ADDRESS REGISTER A AND LOAD DATA MASK
  3433 00002F51 E817000000          <1> 	CALL	CMOS_WRITE	; INITIALIZE STATUS REGISTER A
  3434 00002F56 B482                <1> 	mov	ah, 82h
  3435 00002F58 B00B                <1> 	mov 	al, CMOS_REG_B	; SET "SET BIT" FOR CLOCK INITIALIZATION
  3436 00002F5A E80E000000          <1> 	CALL	CMOS_WRITE	; AND 24 HOUR MODE TO REGISTER B
  3437 00002F5F B00C                <1> 	MOV	AL,CMOS_REG_C	; ADDRESS REGISTER C
  3438 00002F61 E8BBDBFFFF          <1> 	CALL	CMOS_READ	; READ REGISTER C TO INITIALIZE
  3439 00002F66 B00D                <1> 	MOV	AL,CMOS_REG_D	; ADDRESS REGISTER D
  3440                              <1> 	;CALL	CMOS_READ	; READ REGISTER D TO INITIALIZE
  3441                              <1> 	;RETn
  3442                              <1> 	; 12/02/2022
  3443 00002F68 E9B4DBFFFF          <1> 	jmp	CMOS_READ
  3444                              <1> 
  3445                              <1> 	; 15/03/2015
  3446                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3447                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3448 00002F6D 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3449                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3450 00002F6E D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3451 00002F70 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3452 00002F71 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3453 00002F73 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3454 00002F74 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3455 00002F76 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3456 00002F78 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3457 00002F7A B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3458 00002F7C D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3459 00002F7E E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3460 00002F80 90                  <1> 	nop			; I/O DELAY
  3461 00002F81 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3462                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3463 00002F83 9D                  <1> 	popf	
  3464 00002F84 C3                  <1> 	RETn
  3465                              <1> 
  3466                              <1> bf_init:
  3467                              <1> 	; 14/08/2015
  3468                              <1> 	; 02/07/2015
  3469                              <1> 	; 01/07/2015
  3470                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3471                              <1> 	; Buffer (pointer) initialization !
  3472                              <1> 	; 
  3473                              <1> 	; 17/07/2013 - 24/07/2013
  3474                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3475                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3476                              <1> 	;
  3477 00002F85 BF[B8640000]        <1> 	mov	edi, bufp 
  3478 00002F8A B8[C0750000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3479 00002F8F 29D2                <1> 	sub	edx, edx
  3480 00002F91 FECA                <1> 	dec	dl
  3481 00002F93 31C9                <1> 	xor	ecx, ecx
  3482 00002F95 49                  <1> 	dec	ecx
  3483                              <1> bi0:
  3484 00002F96 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3485 00002F9B AB                  <1> 	stosd
  3486 00002F9C 89C6                <1> 	mov	esi, eax
  3487 00002F9E 8916                <1> 	mov	[esi], edx ; 000000FFh
  3488                              <1> 			    ; Not a valid device sign
  3489 00002FA0 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3490                              <1> 		      ; Not a valid block number sign 	 	
  3491 00002FA3 3D[80650000]        <1> 	cmp	eax, buffer
  3492 00002FA8 77EC                <1> 	ja	short bi0
  3493 00002FAA B8[C0750000]        <1> 	mov	eax, sb0
  3494 00002FAF AB                  <1> 	stosd
  3495 00002FB0 B8[C8770000]        <1> 	mov	eax, sb1
  3496 00002FB5 AB                  <1> 	stosd
  3497 00002FB6 89C6                <1> 	mov	esi, eax ; offset sb1
  3498 00002FB8 8916                <1> 	mov	[esi], edx ; 000000FFh
  3499                              <1> 			    ; Not a valid device sign
  3500 00002FBA 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3501                              <1> 		      ; Not a valid block number sign 	 
  3502                              <1> 	; 14/08/2015
  3503                              <1> 	;call 	rdev_init
  3504                              <1> 	;retn
  3505                              <1> 
  3506                              <1> rdev_init: ; root device, super block buffer initialization
  3507                              <1> 	; 01/02/2022
  3508                              <1> 	; 14/08/2015
  3509                              <1> 	; Retro UNIX 386 v1 feature only !
  3510                              <1> 	;
  3511                              <1> 	; NOTE: Disk partitions (file systems), logical
  3512                              <1> 	; drive initialization, partition's start sector etc.
  3513                              <1> 	; will be coded here, later in 'ldrv_init'	
  3514                              <1> 
  3515 00002FBD 0FB605[585C0000]    <1> 	movzx	eax, byte [boot_drv]
  3516                              <1> rdi_0:
  3517 00002FC4 3C80                <1> 	cmp	al, 80h
  3518 00002FC6 7202                <1> 	jb	short rdi_1
  3519 00002FC8 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3520                              <1> rdi_1:
  3521 00002FCA A2[E6640000]        <1> 	mov	[rdev], al
  3522 00002FCF BB[C0750000]        <1>         mov	ebx, sb0 ; super block buffer
  3523 00002FD4 8903                <1> 	mov 	[ebx], eax
  3524 00002FD6 B001                <1> 	mov	al, 1 ; eax = 1
  3525 00002FD8 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3526                              <1> 	;call 	diskio
  3527                              <1> 	;retn
  3528                              <1> 	; 01/02/2022
  3529 00002FDB E91C250000          <1> 	jmp	diskio
  3530                              <1> 
  3531                              <1> ; 23/10/2015
  3532                              <1> com1_irq4:
  3533 00002FE0 [E82F0000]          <1> 	dd dummy_retn
  3534                              <1> com2_irq3:
  3535 00002FE4 [E82F0000]          <1> 	dd dummy_retn
  3536                              <1> 
  3537                              <1> dummy_retn:
  3538 00002FE8 C3                  <1> 	retn
  2052                                  %include 'u1.s'        ; 10/05/2015
  2053                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS1.INC
  2054                              <1> ; Last Modification: 17/07/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 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2065                              <1> ;
  2066                              <1> ; ****************************************************************************
  2067                              <1> ; 23/11/2015
  2068                              <1> 
  2069                              <1> unkni: ; / used for all system calls
  2070                              <1> sysent: ; < enter to system call >
  2071                              <1> 	; 27/02/2022
  2072                              <1> 	; 01/02/2022
  2073                              <1> 	; 19/10/2015
  2074                              <1> 	; 21/09/2015
  2075                              <1> 	; 01/07/2015
  2076                              <1> 	; 19/05/2015
  2077                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2078                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2079                              <1> 	;
  2080                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2081                              <1> 	; The trap type is determined and an indirect jump is made to 
  2082                              <1> 	; the appropriate system call handler. If there is a trap inside
  2083                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2084                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2085                              <1> 	; instructor is decoded to get the the system code part (see
  2086                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2087                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2088                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2089                              <1> 	; is called. If the call is legitimate control passes to the
  2090                              <1> 	; appropriate system routine.
  2091                              <1> 	;
  2092                              <1> 	; Calling sequence:
  2093                              <1> 	;	Through a trap caused by any sys call outside the system.
  2094                              <1> 	; Arguments:
  2095                              <1> 	;	Arguments of particular system call.	
  2096                              <1> 	; ...............................................................
  2097                              <1> 	;	
  2098                              <1> 	; Retro UNIX 8086 v1 modification: 
  2099                              <1> 	;       System call number is in EAX register.
  2100                              <1> 	;
  2101                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2102                              <1> 	;	registers depending of function details.
  2103                              <1>   	;
  2104                              <1> 	; 16/04/2015
  2105 00002FE9 368925[F8640000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2106                              <1> 	; save user registers
  2107 00002FF0 1E                  <1> 	push	ds
  2108 00002FF1 06                  <1> 	push	es
  2109 00002FF2 0FA0                <1> 	push	fs
  2110 00002FF4 0FA8                <1> 	push	gs
  2111 00002FF6 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2112                              <1> 	;
  2113                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2114                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2115                              <1> 	;	for saving/restoring user registers.)
  2116                              <1> 	;
  2117 00002FF7 50                  <1> 	push	eax ; 01/07/2015
  2118 00002FF8 66B81000            <1> 	mov     ax, KDATA
  2119 00002FFC 8ED8                <1>         mov     ds, ax
  2120 00002FFE 8EC0                <1>         mov     es, ax
  2121 00003000 8EE0                <1>         mov     fs, ax
  2122 00003002 8EE8                <1>         mov     gs, ax
  2123 00003004 A1[38610000]        <1> 	mov	eax, [k_page_dir]
  2124 00003009 0F22D8              <1> 	mov	cr3, eax
  2125 0000300C 58                  <1> 	pop	eax ; 01/07/2015
  2126                              <1> 	; 19/10/2015
  2127 0000300D FC                  <1> 	cld
  2128                              <1> 	;
  2129 0000300E FE05[F5640000]      <1> 	inc	byte [sysflg]
  2130                              <1> 		; incb sysflg / indicate a system routine is in progress
  2131 00003014 FB                  <1>         sti 	; 18/01/2014
  2132                              <1> 	;jnz	panic ; 24/05/2013
  2133                              <1> 		; beq 1f
  2134                              <1> 		; jmp panic ; / called if trap inside system
  2135                              <1> 	; 01/02/2022
  2136 00003015 7405                <1> 	jz	short sysent_1
  2137 00003017 E987F9FFFF          <1> 	jmp	panic
  2138                              <1> sysent_1:
  2139                              <1> ;1:	; 16/04/2015
  2140 0000301C A3[00650000]        <1> 	mov	[u.r0], eax
  2141 00003021 8925[FC640000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2142                              <1> 	;
  2143                              <1> 		; mov $s.syst+2,clockp
  2144                              <1> 		; mov r0,-(sp) / save user registers 
  2145                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2146                              <1> 			   ; / in u.r0
  2147                              <1> 		; mov r1,-(sp)
  2148                              <1> 		; mov r2,-(sp)
  2149                              <1> 		; mov r3,-(sp)
  2150                              <1> 		; mov r4,-(sp)
  2151                              <1> 		; mov r5,-(sp)
  2152                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2153                              <1> 		             ; / arithmetic unit
  2154                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2155                              <1> 		             ; / extended arithmetic unit
  2156                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2157                              <1> 		             ; / arithmetic unit
  2158                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2159                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2160                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2161                              <1> 		; sub $sys,r0 / get xxx code
  2162 00003027 C1E002              <1> 	shl	eax, 2
  2163                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2164 0000302A 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2165                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2166                              <1> 	;jnb	short badsys
  2167                              <1> 		; bhis badsys / yes, bad system call
  2168                              <1> 	; 27/02/2022
  2169 0000302F 7205                <1> 	jb	short _2
  2170 00003031 E954010000          <1> 	jmp	badsys
  2171                              <1> _2:
  2172                              <1> 	; 27/02/2022
  2173                              <1> 	;cmc
  2174                              <1> 	;pushf	
  2175                              <1> 	;push	eax
  2176 00003036 8B2D[F8640000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2177                              <1> 	;mov	al, 0FEh ; 11111110b
  2178                              <1> 	;;adc	al, 0 ; al = al + cf
  2179                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2180 0000303C 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2181                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2182                              <1> 				 ; / and clear carry bit
  2183                              <1> 	;pop	ebp ; eax
  2184 00003040 89C5                <1> 	mov	ebp, eax
  2185                              <1> 	;popf
  2186                              <1>         ;;jc	badsys
  2187                              <1> 	; 27/02/2022
  2188                              <1> 	;jnc	short _3
  2189                              <1> 	;jmp	badsys
  2190                              <1> ;_3:
  2191 00003042 A1[00650000]        <1> 	mov	eax, [u.r0]
  2192                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2193 00003047 FFA5[4D300000]      <1> 	jmp	dword [ebp+syscalls]
  2194                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2195                              <1> 		            ; / to proper system routine.
  2196                              <1> syscalls: ; 1:
  2197                              <1> 	; 21/09/2015
  2198                              <1> 	; 01/07/2015
  2199                              <1> 	; 16/04/2015 (32 bit address modification) 
  2200 0000304D [54310000]          <1> 	dd sysrele	; / 0
  2201 00003051 [FC310000]          <1> 	dd sysexit 	; / 1
  2202 00003055 [26330000]          <1> 	dd sysfork 	; / 2
  2203 00003059 [2C340000]          <1> 	dd sysread 	; / 3
  2204 0000305D [3F340000]          <1> 	dd syswrite 	; / 4
  2205 00003061 [A8340000]          <1> 	dd sysopen 	; / 5
  2206 00003065 [D7350000]          <1> 	dd sysclose 	; / 6
  2207 00003069 [A1320000]          <1> 	dd syswait 	; / 7
  2208 0000306D [54350000]          <1> 	dd syscreat 	; / 8
  2209 00003071 [89390000]          <1> 	dd syslink 	; / 9
  2210 00003075 [453A0000]          <1> 	dd sysunlink 	; / 10
  2211 00003079 [0C3B0000]          <1> 	dd sysexec 	; / 11
  2212 0000307D [95410000]          <1> 	dd syschdir 	; / 12
  2213 00003081 [7A420000]          <1> 	dd systime 	; / 13
  2214 00003085 [90350000]          <1> 	dd sysmkdir 	; / 14
  2215 00003089 [E7410000]          <1> 	dd syschmod 	; / 15
  2216 0000308D [4A420000]          <1> 	dd syschown 	; / 16
  2217 00003091 [AD420000]          <1> 	dd sysbreak 	; / 17
  2218 00003095 [CD3E0000]          <1> 	dd sysstat 	; / 18
  2219 00003099 [7D430000]          <1> 	dd sysseek 	; / 19
  2220 0000309D [8F430000]          <1> 	dd systell 	; / 20
  2221 000030A1 [CD4E0000]          <1> 	dd sysmount 	; / 21
  2222 000030A5 [B84F0000]          <1> 	dd sysumount 	; / 22
  2223 000030A9 [0B440000]          <1> 	dd syssetuid 	; / 23
  2224 000030AD [3C440000]          <1> 	dd sysgetuid 	; / 24
  2225 000030B1 [89420000]          <1> 	dd sysstime 	; / 25
  2226 000030B5 [FF430000]          <1> 	dd sysquit 	; / 26
  2227 000030B9 [F3430000]          <1> 	dd sysintr 	; / 27
  2228 000030BD [AA3E0000]          <1> 	dd sysfstat 	; / 28
  2229 000030C1 [EF350000]          <1> 	dd sysemt 	; / 29
  2230 000030C5 [37360000]          <1> 	dd sysmdate 	; / 30
  2231 000030C9 [91360000]          <1> 	dd sysstty 	; / 31
  2232 000030CD [7C380000]          <1> 	dd sysgtty 	; / 32
  2233 000030D1 [32360000]          <1> 	dd sysilgins 	; / 33
  2234 000030D5 [1E570000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2235                              <1> 			     ; 11/06/2014
  2236 000030D9 [35570000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2237                              <1> 			     ; 01/07/2015
  2238 000030DD [0D580000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2239                              <1> 			     ; 21/09/2015 - get last error number
  2240                              <1> end_of_syscalls:
  2241                              <1> 
  2242                              <1> error:
  2243                              <1> 	; 17/09/2015
  2244                              <1> 	; 03/09/2015
  2245                              <1> 	; 01/09/2015
  2246                              <1> 	; 09/06/2015
  2247                              <1> 	; 13/05/2015
  2248                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2249                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2250                              <1> 	;
  2251                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2252                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2253                              <1> 	;
  2254                              <1> 	; INPUTS -> none
  2255                              <1> 	; OUTPUTS ->
  2256                              <1> 	;	processor status - carry (c) bit is set (means error)
  2257                              <1> 	;
  2258                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2259                              <1> 	; 	      Because, jumps to error procedure
  2260                              <1> 	;	      disrupts push-pop nesting balance)
  2261                              <1> 	;
  2262 000030E1 8B2D[F8640000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2263 000030E7 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2264                              <1> 				 ; (system call will return with cf = 1)
  2265                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2266                              <1> 		               ; / users stack
  2267                              <1> 	; 17/09/2015
  2268 000030EB 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2269                              <1> 				 ; for saving/restoring user registers	
  2270                              <1> 	;cmp	ebp, [u.usp]
  2271                              <1> 	;je	short err0	
  2272 000030EE 892D[FC640000]      <1> 	mov	[u.usp], ebp
  2273                              <1> ;err0:
  2274                              <1> 	; 01/09/2015
  2275 000030F4 8B25[FC640000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2276                              <1> 				    ; 10/04/2013
  2277                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2278                              <1> 				    ; related procedures will jump to 'error'
  2279                              <1> 				    ; procedure directly without returning to 
  2280                              <1> 				    ; the caller procedure. So, stack pointer
  2281                              <1>                                     ; must be restored here.)
  2282                              <1> 	; 13/05/2015
  2283                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2284                              <1> 	;	'get last error' system call later. 	
  2285                              <1> 
  2286                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2287 000030FA C605[61650000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2288                              <1> 
  2289                              <1> sysret: ; < return from system call>
  2290                              <1> 	; 01/02/2022
  2291                              <1> 	; 10/09/2015
  2292                              <1> 	; 29/07/2015
  2293                              <1> 	; 25/06/2015
  2294                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2295                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2296                              <1> 	;
  2297                              <1> 	; 'sysret' first checks to see if process is about to be 
  2298                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2299                              <1> 	; If not, following happens:	 
  2300                              <1> 	; 	1) The user's stack pointer is restored.
  2301                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2302                              <1> 	;	   i-node has been modified. If it has, it is written out
  2303                              <1> 	;	   via 'ppoke'.
  2304                              <1> 	;	3) If the super block has been modified, it is written out
  2305                              <1> 	;	   via 'ppoke'.				
  2306                              <1> 	;	4) If the dismountable file system's super block has been
  2307                              <1> 	;	   modified, it is written out to the specified device
  2308                              <1> 	;	   via 'ppoke'.
  2309                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2310                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2311                              <1> 	;	   another user a chance to run.
  2312                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2313                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2314                              <1> 	;
  2315                              <1> 	; Calling sequence:
  2316                              <1> 	;	jump table or 'br sysret'
  2317                              <1> 	; Arguments: 
  2318                              <1> 	;	-	
  2319                              <1> 	; ...............................................................
  2320                              <1> 	;	
  2321                              <1> 	; ((AX=r1 for 'iget' input))
  2322                              <1> 	;	
  2323                              <1> 	;xor	ax, ax ; 04/05/2013
  2324                              <1> 	; 01/02/2022
  2325 00003101 31C0                <1> 	xor	eax, eax
  2326                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2327 00003103 FEC0                <1> 	inc	al ; 04/05/2013
  2328 00003105 3805[48650000]      <1> 	cmp	[u.bsys], al ; 1
  2329                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2330                              <1>         ;jnb	sysexit ; 04/05/2013
  2331                              <1> 		; bne sysexit / of an error? yes, go to sysexit
  2332                              <1> 	; 01/02/2022
  2333 0000310B 7205                <1> 	jb	short sysret_2
  2334 0000310D E9EA000000          <1> 	jmp	sysexit
  2335                              <1> sysret_2:
  2336                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2337                              <1> 		; mov u.sp,sp / no point stack to users stack
  2338 00003112 FEC8                <1> 	dec 	al ; mov ax, 0
  2339                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2340 00003114 E8DD160000          <1> 	call	iget
  2341                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2342                              <1> 		            ; / it is written out
  2343 00003119 6631C0              <1> 	xor 	ax, ax ; 0
  2344 0000311C 3805[F3640000]      <1> 	cmp	[smod], al ; 0
  2345                              <1> 		; tstb	smod / has the super block been modified
  2346 00003122 7614                <1> 	jna	short sysret1
  2347                              <1> 		; beq	1f / no, 1f
  2348 00003124 A2[F3640000]        <1> 	mov	[smod], al ; 0
  2349                              <1> 		; clrb smod / yes, clear smod
  2350 00003129 BB[C0750000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2351 0000312E 66810B0002          <1>    	or	word [ebx], 200h ;;
  2352                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2353                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2354                              <1> 		      	      ; / output
  2355                              <1> 	; AX = 0
  2356 00003133 E828230000          <1> 	call 	poke ; 07/08/2013
  2357                              <1> 	;call	ppoke
  2358                              <1> 	; AX = 0
  2359                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2360                              <1> sysret1: ;1:
  2361 00003138 3805[F4640000]      <1> 	cmp	[mmod], al ; 0
  2362                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2363                              <1> 		           ; / system
  2364 0000313E 7614                <1> 	jna	short sysrel0
  2365                              <1> 		; beq 1f / been modified?  no, 1f
  2366 00003140 A2[F4640000]        <1> 	mov	[mmod], al ; 0	
  2367                              <1> 		; clrb	mmod / yes, clear mmod
  2368                              <1>         ;mov    ax, [mntd]
  2369                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2370 00003145 BB[C8770000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2371                              <1>         ;;mov	[ebx], al
  2372                              <1> 	;mov    [sb1], al
  2373                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2374 0000314A 66810B0002          <1> 	or	word [ebx], 200h
  2375                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2376                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2377 0000314F E80C230000          <1> 	call	poke ; 07/08/2013
  2378                              <1> 	;call	ppoke 
  2379                              <1> 		; jsr r0,ppoke / write it out to its device
  2380                              <1>         ;xor    al, al ; 26/04/2013       
  2381                              <1> ;1:
  2382                              <1> 		; tstb uquant / is the time quantum 0?
  2383                              <1> 		; bne 1f / no, don't swap it out
  2384                              <1> 
  2385                              <1> sysrele: ; < release >
  2386                              <1> 	; 14/10/2015
  2387                              <1> 	; 01/09/2015
  2388                              <1> 	; 24/07/2015
  2389                              <1> 	; 14/05/2015
  2390                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2391                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2392                              <1> 	;
  2393                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2394                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2395                              <1> 	; turns off the system flag. It then checked to see if there is
  2396                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2397                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2398                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2399                              <1> 	; the user, a rti is made.
  2400                              <1> 	;
  2401                              <1> 	; Calling sequence:
  2402                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2403                              <1> 	; Arguments:
  2404                              <1> 	;	-	
  2405                              <1> 	; ...............................................................
  2406                              <1> 	;	
  2407                              <1> 	; 23/02/2014 (swapret)
  2408                              <1> 	; 22/09/2013
  2409                              <1> sysrel0: ;1:
  2410 00003154 803D[3C650000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2411                              <1> 		; tstb uquant / is the time quantum 0?
  2412 0000315B 7705                <1>         ja      short swapret
  2413                              <1> 		; bne 1f / no, don't swap it out
  2414                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2415 0000315D E82A130000          <1> 	call	tswap
  2416                              <1> 		; jsr r0,tswap / yes, swap it out
  2417                              <1> ;
  2418                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2419                              <1> swapret: ;1:
  2420                              <1> 	; 10/09/2015
  2421                              <1> 	; 01/09/2015
  2422                              <1> 	; 14/05/2015
  2423                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2424                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2425                              <1> 	; cli
  2426                              <1> 	; 24/07/2015
  2427                              <1> 	;
  2428                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2429                              <1> 	;; mov	esp, [u.usp]
  2430                              <1> 
  2431                              <1> 	; 22/09/2013
  2432 00003162 E8FC140000          <1> 	call	isintr
  2433                              <1> 	; 20/10/2013
  2434 00003167 7405                <1> 	jz	short sysrel1
  2435 00003169 E877000000          <1> 	call	intract
  2436                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2437                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2438                              <1> 		               ; / action
  2439                              <1> sysrel1:
  2440 0000316E FA                  <1> 	cli ; 14/10/2015
  2441 0000316F FE0D[F5640000]      <1> 	dec	byte [sysflg]
  2442                              <1> 		; decb sysflg / turn system flag off
  2443 00003175 A1[53650000]        <1> 	mov     eax, [u.pgdir]
  2444 0000317A 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2445                              <1> 			  ; (others are different than kernel page tables) 
  2446                              <1> 	; 10/09/2015
  2447 0000317D 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2448                              <1> 		; mov (sp)+,sc / restore user registers
  2449                              <1> 		; mov (sp)+,mq
  2450                              <1> 		; mov (sp)+,ac
  2451                              <1> 		; mov (sp)+,r5
  2452                              <1> 		; mov (sp)+,r4
  2453                              <1> 		; mov (sp)+,r3
  2454                              <1> 		; mov (sp)+,r2
  2455                              <1> 	;
  2456 0000317E A1[00650000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2457 00003183 0FA9                <1> 	pop	gs
  2458 00003185 0FA1                <1> 	pop	fs
  2459 00003187 07                  <1> 	pop	es
  2460 00003188 1F                  <1> 	pop	ds
  2461 00003189 CF                  <1> 	iretd	
  2462                              <1> 		; rti / no, return from interrupt
  2463                              <1> 
  2464                              <1> badsys:
  2465                              <1> 	; 27/02/2022
  2466                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2467                              <1> 	; (Major Modification: 'core' dumping procedure in
  2468                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2469                              <1> 	;	has been changed to print 'Invalid System Call !'
  2470                              <1> 	;	message on the user's console tty.)
  2471                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2472                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2473                              <1> 	; (EAX = Function number)  
  2474                              <1> 	;
  2475 0000318A FE05[48650000]      <1> 	inc	byte [u.bsys]
  2476                              <1> 	;
  2477 00003190 8B1D[F8640000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2478 00003196 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2479 00003198 E846E4FFFF          <1> 	call	dwordtohex
  2480 0000319D 8915[965E0000]      <1> 	mov	[bsys_msg_eip], edx
  2481 000031A3 A3[9A5E0000]        <1> 	mov	[bsys_msg_eip+4], eax
  2482 000031A8 A1[00650000]        <1> 	mov	eax, [u.r0]
  2483 000031AD E831E4FFFF          <1> 	call	dwordtohex
  2484 000031B2 8915[865E0000]      <1> 	mov	[bsys_msg_eax], edx
  2485 000031B8 A3[8A5E0000]        <1> 	mov	[bsys_msg_eax+4], eax
  2486                              <1> 	; 27/02/2022
  2487                              <1> 	;xor	eax, eax
  2488                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2489                              <1> 	;mov	ebx, [u.fofp]
  2490                              <1> 	;mov	[ebx], eax
  2491                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2492                              <1> 	;inc	eax
  2493                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2494                              <1> 		; writei
  2495                              <1> 		; INPUTS ->
  2496                              <1> 		;    r1 - inode number
  2497                              <1> 		;    u.count - byte count to be written
  2498                              <1> 		;    u.base - points to user buffer
  2499                              <1> 		;    u.fofp - points to word with current file offset
  2500                              <1> 		; OUTPUTS ->
  2501                              <1> 		;    u.count - cleared
  2502                              <1> 		;    u.nread - accumulates total bytes passed back	
  2503                              <1> 		;
  2504                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2505                              <1> 	;call	writei
  2506                              <1> 	;;mov	eax, 1
  2507                              <1> 	;jmp	sysexit
  2508                              <1> 
  2509                              <1> 	; 27/02/2022
  2510 000031BD BE[675E0000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2511 000031C2 0FB61D[49650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2512 000031C9 8A83[53620000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2513 000031CF C605[67610000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2514 000031D6 A2[4E650000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2515 000031DB E812260000          <1> 	call	print_cmsg
  2516                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2517 000031E0 E9FCFEFFFF          <1> 	jmp	error
  2518                              <1> 
  2519                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2520                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2521                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2522                              <1> 		; br 1f / error
  2523                              <1> 		; neg r1 / negate the i-number to open the core image file
  2524                              <1> 		       ; / for writing
  2525                              <1> 		; jsr r0,iopen / open the core image file
  2526                              <1> 		; jsr r0,itrunc / free all associated blocks
  2527                              <1> 		; br 2f
  2528                              <1> ;1:
  2529                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2530                              <1> 		; jsr r0,maknod / make an i-node
  2531                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2532                              <1> ;2:
  2533                              <1> 		; mov $core,u.base / move address core to u.base
  2534                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2535                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2536                              <1> 		; clr u.off / clear user offset
  2537                              <1> 		; jsr r0,writei / write out the core image to the user
  2538                              <1> 		; mov $user,u.base / pt. u.base to user
  2539                              <1> 		; mov $64.,u.count / u.count = 64
  2540                              <1> 		; jsr r0,writei / write out all the user parameters
  2541                              <1> 		; neg r1 / make i-number positive
  2542                              <1> 		; jsr r0,iclose / close the core image file
  2543                              <1> 		; br sysexit /
  2544                              <1> ;3:
  2545                              <1> 		; <core\0\0>
  2546                              <1> 
  2547                              <1> intract: ; / interrupt action
  2548                              <1> 	; 14/10/2015
  2549                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2550                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2551                              <1> 	;
  2552                              <1> 	; Retro UNIX 8086 v1 modification !
  2553                              <1> 	; (Process/task switching and quit routine by using
  2554                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2555                              <1> 	;
  2556                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2557                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2558                              <1> 	;		'intract' will jump to 'sysexit'.
  2559                              <1> 	;	    Intract will return to the caller 
  2560                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2561                              <1> 	; 14/10/2015
  2562 000031E5 FB                  <1> 	sti
  2563                              <1> 	; 07/12/2013	
  2564 000031E6 66FF05[40650000]    <1> 	inc 	word [u.quit]
  2565 000031ED 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2566 000031EF 66FF0D[40650000]    <1> 	dec	word [u.quit]
  2567                              <1> 	; 16/04/2015
  2568 000031F6 C3                  <1> 	retn
  2569                              <1> intrct0:	
  2570 000031F7 58                  <1> 	pop	eax ; call intract -> retn
  2571                              <1> 	;
  2572 000031F8 31C0                <1> 	xor 	eax, eax
  2573 000031FA FEC0                <1> 	inc	al  ; mov ax, 1
  2574                              <1> ;;;
  2575                              <1> 	; UNIX v1 original 'intract' routine... 
  2576                              <1> 	; / interrupt action
  2577                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2578                              <1> 		; bne 1f / no, 1f
  2579                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2580                              <1> 	; 1: / now in user area
  2581                              <1> 		; mov r1,-(sp) / save r1
  2582                              <1> 		; mov u.ttyp,r1 
  2583                              <1> 			; / pointer to tty buffer in control-to r1
  2584                              <1> 		; cmpb 6(r1),$177
  2585                              <1> 			; / is the interrupt char equal to "del"
  2586                              <1> 		; beq 1f / yes, 1f
  2587                              <1> 		; clrb 6(r1) 
  2588                              <1> 		        ; / no, clear the byte 
  2589                              <1> 			; / (must be a quit character)
  2590                              <1> 		; mov (sp)+,r1 / restore r1
  2591                              <1> 		; clr u.quit / clear quit flag
  2592                              <1> 		; bis $20,2(sp) 
  2593                              <1> 		    	; / set trace for quit (sets t bit of 
  2594                              <1> 			; / ps-trace trap)
  2595                              <1> 		; rti   ;  / return from interrupt
  2596                              <1> 	; 1: / interrupt char = del
  2597                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2598                              <1> 			   ; / in the buffer
  2599                              <1> 		; mov (sp)+,r1 / restore r1
  2600                              <1> 		; cmp u.intr,$core / should control be 
  2601                              <1> 				; / transferred to loc core?
  2602                              <1> 		; blo 1f
  2603                              <1> 		; jmp *u.intr / user to do rti yes, 
  2604                              <1> 				; / transfer to loc core
  2605                              <1> 	; 1:
  2606                              <1> 		; sys 1 / exit
  2607                              <1> 
  2608                              <1> sysexit: ; <terminate process>
  2609                              <1> 	; 17/07/2022
  2610                              <1> 	; 01/02/2022
  2611                              <1> 	; 01/09/2015
  2612                              <1> 	; 31/08/2015
  2613                              <1> 	; 14/05/2015
  2614                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2615                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2616                              <1> 	;
  2617                              <1> 	; 'sysexit' terminates a process. First each file that
  2618                              <1> 	; the process has opened is closed by 'flose'. The process
  2619                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2620                              <1> 	; searched to find children of the dying process. If any of
  2621                              <1> 	; children are zombies (died by not waited for), they are
  2622                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2623                              <1> 	; dying process's parent. When the parent is found, it is
  2624                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2625                              <1> 	; one of these, the dying process just dies. If it is waiting
  2626                              <1> 	; for a child process to die, it notified that it doesn't 
  2627                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2628                              <1> 	; (waiting to active). It is awakened and put on runq by
  2629                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2630                              <1> 	; it will never be run again but stays around until a 'wait'
  2631                              <1> 	; is completed by it's parent process. If the parent is not
  2632                              <1> 	; found, process just dies. This means 'swap' is called with
  2633                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2634                              <1> 	; to write out the process and 'rswap' reads the new process
  2635                              <1> 	; over the one that dies..i.e., the dying process is 
  2636                              <1> 	; overwritten and destroyed.	
  2637                              <1>  	;
  2638                              <1> 	; Calling sequence:
  2639                              <1> 	;	sysexit or conditional branch.
  2640                              <1> 	; Arguments:
  2641                              <1> 	;	-	
  2642                              <1> 	; ...............................................................
  2643                              <1> 	;	
  2644                              <1> 	; Retro UNIX 8086 v1 modification: 
  2645                              <1> 	;       System call number (=1) is in EAX register.
  2646                              <1> 	;
  2647                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2648                              <1> 	;       registers depending of function details.
  2649                              <1> 	;
  2650                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2651                              <1> 	;
  2652                              <1> ; / terminate process
  2653                              <1> 	; AX = 1
  2654                              <1> 	;dec 	ax ; 0
  2655                              <1> 	; 01/02/2022
  2656 000031FC 48                  <1> 	dec	eax ; 0
  2657 000031FD 66A3[3E650000]      <1> 	mov	[u.intr], ax ; 0
  2658                              <1> 		; clr u.intr / clear interrupt control word
  2659                              <1> 		; clr r1 / clear r1
  2660                              <1> 	; AX = 0
  2661                              <1> sysexit_1: ; 1:
  2662                              <1> 	; AX = File descriptor
  2663                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2664                              <1> 		; / Search the whole list
  2665 00003203 E8630D0000          <1> 	call	fclose
  2666                              <1> 		; jsr r0,fclose / close all files the process opened
  2667                              <1> 	;; ignore error return
  2668                              <1> 		; br .+2 / ignore error return
  2669                              <1> 	;inc	ax
  2670 00003208 FEC0                <1> 	inc	al
  2671                              <1> 		; inc r1 / increment file descriptor
  2672                              <1> 	;cmp	ax, 10
  2673 0000320A 3C0A                <1> 	cmp	al, 10
  2674                              <1> 		; cmp r1,$10. / end of u.fp list?
  2675 0000320C 72F5                <1> 	jb	short sysexit_1
  2676                              <1> 		; blt 1b / no, go back
  2677 0000320E 0FB61D[49650000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2678                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2679 00003215 88A3[73620000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2680                              <1> 		; clrb p.stat-1(r1) / free the process
  2681                              <1> 	;shl	bx, 1
  2682 0000321B D0E3                <1> 	shl	bl, 1
  2683                              <1> 		; asl r1 / use r1 for index into the below tables
  2684 0000321D 668B8B[12620000]    <1> 	mov	cx, [ebx+p.pid-2]
  2685                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2686 00003224 668B93[32620000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2687                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2688                              <1> 	;xor 	bx, bx ; 0
  2689 0000322B 30DB                <1> 	xor	bl, bl ; 0
  2690                              <1> 		; clr r2
  2691 0000322D 31F6                <1> 	xor	esi, esi ; 0
  2692                              <1> 		; clr r5 / initialize reg
  2693                              <1> sysexit_2: ; 1:
  2694                              <1> 	        ; / find children of this dying process, 
  2695                              <1> 		; / if they are zombies, free them
  2696                              <1> 	;add	bx, 2
  2697 0000322F 80C302              <1> 	add	bl, 2
  2698                              <1> 		; add $2,r2 / search parent process table 
  2699                              <1> 		          ; / for dying process's name
  2700 00003232 66398B[32620000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2701                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2702 00003239 7513                <1> 	jne	short sysexit_4
  2703                              <1> 		; bne 3f / no
  2704                              <1> 	;shr	bx, 1
  2705 0000323B D0EB                <1> 	shr	bl, 1
  2706                              <1> 		; asr r2 / yes, it is a parent
  2707 0000323D 80BB[73620000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2708                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2709                              <1> 				     ; / dying process a zombie
  2710 00003244 7506                <1> 	jne	short sysexit_3 
  2711                              <1> 		; bne 2f / no
  2712 00003246 88A3[73620000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2713                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2714                              <1> sysexit_3: ; 2:
  2715                              <1> 	;shr	bx, 1
  2716 0000324C D0E3                <1> 	shl	bl, 1
  2717                              <1> 		; asl r2
  2718                              <1> sysexit_4: ; 3:
  2719                              <1> 		; / search the process name table 
  2720                              <1> 		; / for the dying process's parent
  2721 0000324E 663993[12620000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2722                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2723 00003255 7502                <1> 	jne	short sysexit_5
  2724                              <1> 		; bne 3f / no
  2725 00003257 89DE                <1> 	mov	esi, ebx
  2726                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2727                              <1> 		          ; / process # x2) in r5
  2728                              <1> sysexit_5: ; 3:
  2729                              <1> 	;cmp	bx, nproc + nproc
  2730 00003259 80FB20              <1> 	cmp	bl, nproc + nproc
  2731                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2732 0000325C 72D1                <1> 	jb	short sysexit_2
  2733                              <1> 		; blt 1b / no, go back
  2734                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2735 0000325E 21F6                <1> 	and	esi, esi ; r5=r1
  2736 00003260 7430                <1> 	jz	short sysexit_6
  2737                              <1> 		; beq 2f / no parent has been found. 
  2738                              <1> 		       ; / The process just dies
  2739                              <1> 	;shr	si, 1
  2740                              <1> 	; 17/07/2022
  2741 00003262 D1EE                <1> 	shr	esi, 1
  2742                              <1> 		; asr r1 / set up index to p.stat
  2743 00003264 8A86[73620000]      <1> 	mov	al, [esi+p.stat-1]
  2744                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2745 0000326A 20C0                <1> 	and	al, al
  2746 0000326C 7424                <1> 	jz	short sysexit_6
  2747                              <1> 		; beq 2f / if its been freed, 2f
  2748 0000326E 3C03                <1> 	cmp	al, 3
  2749                              <1> 		; cmp r2,$3 / is parent a zombie?
  2750 00003270 7420                <1> 	je	short sysexit_6
  2751                              <1> 		; beq 2f / yes, 2f
  2752                              <1> 	; BH = 0
  2753 00003272 8A1D[49650000]      <1> 	mov	bl, [u.uno]
  2754                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2755 00003278 C683[73620000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2756                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2757                              <1> 	; 05/02/2014
  2758 0000327F 3C01                <1> 	cmp	al, 1 ; SRUN
  2759 00003281 740F                <1> 	je	short sysexit_6
  2760                              <1> 	;cmp	al, 2
  2761                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2762                              <1> 			  ; / this child to die
  2763                              <1> 	;jne	short sysexit_6	
  2764                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2765                              <1> 	; 05/02/2014
  2766                              <1> 	; p.stat = 2 --> waiting
  2767                              <1> 	; p.stat = 4 --> sleeping
  2768 00003283 C686[73620000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2769                              <1> 	;dec	byte [esi+p.stat-1]
  2770                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2771 0000328A 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2772                              <1> 	; 
  2773                              <1> 	;mov	ebx, runq + 4
  2774                              <1> 		; mov $runq+4,r2 / on the runq
  2775 0000328D E8D1120000          <1> 	call	putlu
  2776                              <1> 		; jsr r0, putlu
  2777                              <1> sysexit_6: ; 2:
  2778                              <1> 	; 31/08/2015
  2779                              <1> 		; / the process dies
  2780 00003292 C605[49650000]00    <1> 	mov	byte [u.uno], 0
  2781                              <1> 		; clrb u.uno / put zero as the process number, 
  2782                              <1> 	           ; / so "swap" will
  2783 00003299 E8F8110000          <1> 	call	swap
  2784                              <1> 		; jsr r0,swap / overwrite process with another process
  2785                              <1> hlt_sys:
  2786                              <1> 	;sti ; 18/01/2014
  2787                              <1> hlts0:
  2788 0000329E F4                  <1> 	hlt
  2789 0000329F EBFD                <1> 	jmp	short hlts0
  2790                              <1> 		; 0 / and thereby kill it; halt?
  2791                              <1> 
  2792                              <1> 
  2793                              <1> syswait: ; < wait for a processs to die >
  2794                              <1> 	; 12/02/2022
  2795                              <1> 	; 01/02/2022
  2796                              <1> 	; 17/09/2015
  2797                              <1> 	; 02/09/2015
  2798                              <1> 	; 01/09/2015
  2799                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2800                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2801                              <1> 	;
  2802                              <1> 	; 'syswait' waits for a process die. 
  2803                              <1> 	; It works in following way:
  2804                              <1> 	;    1) From the parent process number, the parent's 
  2805                              <1> 	; 	process name is found. The p.ppid table of parent
  2806                              <1> 	;	names is then searched for this process name.
  2807                              <1> 	;	If a match occurs, r2 contains child's process
  2808                              <1> 	;	number. The child status is checked to see if it is
  2809                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2810                              <1> 	;	If it is, the child process is freed and it's name
  2811                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2812                              <1> 	;	If the child is not a zombie, nothing happens and
  2813                              <1> 	;	the search goes on through the p.ppid table until
  2814                              <1> 	;	all processes are checked or a zombie is found.
  2815                              <1> 	;    2) If no zombies are found, a check is made to see if
  2816                              <1> 	;	there are any children at all. If there are none,
  2817                              <1> 	;	an error return is made. If there are, the parent's
  2818                              <1> 	;	status is set to 2 (waiting for child to die),
  2819                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2820                              <1> 	;	is made to wait on the next process.
  2821                              <1> 	;
  2822                              <1> 	; Calling sequence:
  2823                              <1> 	;	?
  2824                              <1> 	; Arguments:
  2825                              <1> 	;	-
  2826                              <1> 	; Inputs: - 
  2827                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2828                              <1> 	; ...............................................................
  2829                              <1> 	;				
  2830                              <1> 	
  2831                              <1> ; / wait for a process to die
  2832                              <1> 
  2833                              <1> syswait_0:
  2834 000032A1 0FB61D[49650000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2835                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2836 000032A8 D0E3                <1> 	shl	bl, 1
  2837                              <1> 	;shl	bx, 1
  2838                              <1> 		; asl r1 / x2 to get index into p.pid table
  2839 000032AA 668B83[12620000]    <1> 	mov	ax, [ebx+p.pid-2]
  2840                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2841 000032B1 31F6                <1> 	xor	esi, esi
  2842                              <1> 		; clr r2
  2843 000032B3 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2844                              <1> 	;xor 	cl, cl
  2845                              <1> 		; clr r3 / initialize reg 3
  2846                              <1> syswait_1: ; 1:
  2847                              <1> 	; 12/02/2022
  2848 000032B5 46                  <1> 	inc	esi
  2849 000032B6 46                  <1> 	inc	esi
  2850                              <1> 	;add	si, 2
  2851                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2852                              <1> 			  ; / search table of parent processes 
  2853                              <1> 			  ; / for this process name
  2854 000032B7 663B86[32620000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2855                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2856                              <1> 			            ; / process number
  2857 000032BE 7531                <1> 	jne	short syswait_3
  2858                              <1> 		; bne 3f / branch if no match of parent process name
  2859                              <1> 	;inc	cx
  2860 000032C0 FEC1                <1> 	inc	cl
  2861                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2862                              <1> 	; 12/02/2022
  2863 000032C2 D1EE                <1> 	shr	esi, 1
  2864                              <1> 	;shr	si, 1
  2865                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2866                              <1> 	; The possible states ('p.stat' values) of a process are:
  2867                              <1> 	;	0 = free or unused
  2868                              <1> 	;	1 = active
  2869                              <1> 	;	2 = waiting for a child process to die
  2870                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2871 000032C4 80BE[73620000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2872                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2873 000032CB 7522                <1> 	jne	short syswait_2
  2874                              <1> 		; bne 2f / no, skip it
  2875 000032CD 88BE[73620000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2876                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2877                              <1> 	; 12/02/2022
  2878 000032D3 D1E6                <1> 	shl	esi, 1
  2879                              <1> 	;shl	si, 1
  2880                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2881 000032D5 0FB786[12620000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2882 000032DC A3[00650000]        <1> 	mov	[u.r0], eax
  2883                              <1> 		; mov p.pid-2(r2),*u.r0 
  2884                              <1> 			      ; / put childs process name in (u.r0)
  2885                              <1> 	;
  2886                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2887                              <1> 	;
  2888                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2889                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2890                              <1> 	; system call loop from the application/program if it calls
  2891                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2892                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2893                              <1> 	;
  2894                              <1> 	; Note: syswait will return with error if there is not a
  2895                              <1> 	;       zombie or running process to wait.	
  2896                              <1> 	;
  2897                              <1> 	;sub	ax, ax
  2898                              <1> 	; 01/02/2022
  2899 000032E1 29C0                <1> 	sub	eax, eax
  2900 000032E3 668986[32620000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2901 000032EA E914FEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2902                              <1> 	;
  2903                              <1> 	;jmp	sysret
  2904                              <1> 		; br sysret1 / return cause child is dead
  2905                              <1> syswait_2: ; 2:
  2906                              <1> 	; 12/02/2022
  2907 000032EF D1E6                <1> 	shl	esi, 1
  2908                              <1> 	;shl	si, 1
  2909                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2910                              <1> syswait_3: ; 3:
  2911 000032F1 6683FE20            <1> 	cmp	si, nproc+nproc
  2912                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2913 000032F5 72BE                <1> 	jb	short syswait_1
  2914                              <1> 		; blt 1b / no, continue search
  2915                              <1> 	;and	cx, cx
  2916 000032F7 20C9                <1> 	and	cl, cl
  2917                              <1> 		; tst r3 / one gets here if there are no children 
  2918                              <1> 		       ; / or children that are still active
  2919                              <1> 	; 30/10/2013
  2920 000032F9 7515                <1> 	jnz	short syswait_4
  2921                              <1> 	;jz	error
  2922                              <1> 		; beq error1 / there are no children, error
  2923 000032FB 890D[00650000]      <1> 	mov	[u.r0], ecx ; 0
  2924                              <1> 	; 12/02/2022
  2925 00003301 C705[4F650000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2925 00003309 0000                <1>
  2926                              <1> 			; miscellaneous/other errors
  2927 0000330B E9D1FDFFFF          <1> 	jmp	error
  2928                              <1> syswait_4:
  2929 00003310 8A1D[49650000]      <1> 	mov	bl, [u.uno]
  2930                              <1> 		; movb u.uno,r1 / there are children so put 
  2931                              <1> 			      ; / parent process number in r1
  2932 00003316 FE83[73620000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2933                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2934                              <1> 				  ; / other children to die
  2935                              <1> 	; 04/11/2013
  2936 0000331C E875110000          <1> 	call	swap
  2937                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2938 00003321 E97BFFFFFF          <1> 	jmp	syswait_0
  2939                              <1> 		; br syswait / wait on next process
  2940                              <1> 
  2941                              <1> sysfork: ; < create a new process >
  2942                              <1> 	; 26/02/2022
  2943                              <1> 	; 25/02/2022
  2944                              <1> 	; 01/02/2022
  2945                              <1> 	; 18/09/2015
  2946                              <1> 	; 04/09/2015
  2947                              <1> 	; 02/09/2015
  2948                              <1> 	; 01/09/2015
  2949                              <1> 	; 28/08/2015
  2950                              <1> 	; 14/05/2015
  2951                              <1> 	; 10/05/2015
  2952                              <1> 	; 09/05/2015
  2953                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2954                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2955                              <1> 	;
  2956                              <1> 	; 'sysfork' creates a new process. This process is referred
  2957                              <1> 	; to as the child process. This new process core image is
  2958                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2959                              <1> 	; distinction is the return location and the fact that (u.r0)
  2960                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2961                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2962                              <1> 	; 'sysfork' works in the following manner: 	
  2963                              <1> 	;    1) The process status table (p.stat) is searched to find
  2964                              <1> 	;	a process number that is unused. If none are found
  2965                              <1> 	;	an error occurs.
  2966                              <1> 	;    2) when one is found, it becomes the child process number
  2967                              <1> 	;	and it's status (p.stat) is set to active.
  2968                              <1> 	;    3) If the parent had a control tty, the interrupt 
  2969                              <1> 	;	character in that tty buffer is cleared.
  2970                              <1> 	;    4) The child process is put on the lowest priority run 
  2971                              <1> 	;	queue via 'putlu'.
  2972                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  2973                              <1> 	;	it is a unique number) and is put in the child's unique
  2974                              <1> 	;	identifier; process id (p.pid).
  2975                              <1> 	;    6) The process name of the parent is then obtained and
  2976                              <1> 	;	placed in the unique identifier of the parent process
  2977                              <1> 	;	name is then put in 'u.r0'.	
  2978                              <1> 	;    7) The child process is then written out on disk by
  2979                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  2980                              <1> 	;	and the child is born. (The child process is written 
  2981                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  2982                              <1> 	;	number.)
  2983                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  2984                              <1> 	;    9) The child process name is put in 'u.r0'.
  2985                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  2986                              <1> 	;	create the return address for the parent process.
  2987                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  2988                              <1> 	;	the parent has opened. For each file the parent has
  2989                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  2990                              <1> 	;	to indicate that the child process also has opened
  2991                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  2992                              <1> 	;
  2993                              <1> 	; Calling sequence:
  2994                              <1> 	;	from shell ?
  2995                              <1> 	; Arguments:
  2996                              <1> 	;	-
  2997                              <1> 	; Inputs: -
  2998                              <1> 	; Outputs: *u.r0 - child process name
  2999                              <1> 	; ...............................................................
  3000                              <1> 	;	
  3001                              <1> 	; Retro UNIX 8086 v1 modification: 
  3002                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3003                              <1> 	;	= process id of child a parent process returns
  3004                              <1> 	;	= process id of parent when a child process returns
  3005                              <1> 	;
  3006                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3007                              <1> 	;	in following manner: (with an example: c library, fork)
  3008                              <1> 	;	
  3009                              <1> 	;	1:
  3010                              <1> 	;		sys	fork
  3011                              <1> 	;			br 1f  / child process returns here
  3012                              <1> 	;		bes	2f     / parent process returns here
  3013                              <1> 	;		/ pid of new process in r0
  3014                              <1> 	;		rts	pc
  3015                              <1> 	;	2: / parent process condionally branches here
  3016                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3017                              <1> 	;		rts	pc
  3018                              <1> 	;
  3019                              <1> 	;	1: / child process brances here
  3020                              <1> 	;		clr	r0   / pid = 0 in child process
  3021                              <1> 	;		rts	pc
  3022                              <1> 	;
  3023                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3024                              <1> 	;		// pid = fork();
  3025                              <1> 	;		//
  3026                              <1> 	;		// pid == 0 in child process; 
  3027                              <1> 	;		// pid == -1 means error return
  3028                              <1> 	;		// in child, 
  3029                              <1> 	;		//	parents id is in par_uid if needed
  3030                              <1> 	;		
  3031                              <1> 	;		_fork:
  3032                              <1> 	;			mov	$.fork,eax
  3033                              <1> 	;			int	$0x30
  3034                              <1> 	;			jmp	1f
  3035                              <1> 	;			jnc	2f
  3036                              <1> 	;			jmp	cerror
  3037                              <1> 	;		1:
  3038                              <1> 	;			mov	eax,_par_uid
  3039                              <1> 	;			xor	eax,eax
  3040                              <1> 	;		2:
  3041                              <1> 	;			ret
  3042                              <1> 	;
  3043                              <1> 	;	In Retro UNIX 8086 v1,
  3044                              <1> 	;	'sysfork' returns in following manner:
  3045                              <1> 	;	
  3046                              <1> 	;		mov	ax, sys_fork
  3047                              <1> 	;		mov	bx, offset @f ; routine for child
  3048                              <1> 	;		int	20h
  3049                              <1> 	;		jc	error
  3050                              <1> 	;		
  3051                              <1> 	;	; Routine for parent process here (just after 'jc')
  3052                              <1> 	;		mov	word ptr [pid_of_child], ax
  3053                              <1> 	;		jmp	next_routine_for_parent	
  3054                              <1> 	;
  3055                              <1> 	;	@@: ; routine for child process here				
  3056                              <1> 	;		....	
  3057                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3058                              <1> 	;	       for child process by using BX input.
  3059                              <1> 	;	      (at first, parent process will return then 
  3060                              <1> 	;	      child process will return -after swapped in-
  3061                              <1> 	;	      'syswait' is needed in parent process
  3062                              <1> 	;	      if return from child process will be waited for.)
  3063                              <1> 	;	  				
  3064                              <1> 	
  3065                              <1> ; / create a new process
  3066                              <1> 	; EBX = return address for child process 
  3067                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3068 00003326 31F6                <1> 	xor 	esi, esi
  3069                              <1> 		; clr r1
  3070                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3071 00003328 46                  <1> 	inc	esi
  3072                              <1> 		; inc r1
  3073 00003329 80BE[73620000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3074                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3075 00003330 760B                <1> 	jna	short sysfork_2	
  3076                              <1> 		; beq 1f / it's unused so branch
  3077 00003332 6683FE10            <1> 	cmp	si, nproc
  3078                              <1> 		; cmp r1,$nproc / all processes checked
  3079 00003336 72F0                <1> 	jb	short sysfork_1
  3080                              <1> 		; blt 1b / no, branch back
  3081                              <1> 	;
  3082                              <1> 	; Retro UNIX 8086 v1. modification:
  3083                              <1> 	;	Parent process returns from 'sysfork' to address 
  3084                              <1> 	;	which is just after 'sysfork' system call in parent
  3085                              <1> 	;	process. Child process returns to address which is put
  3086                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3087                              <1> 	;
  3088                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3089                              <1> 		               ; / to old process return
  3090                              <1> 		; br error1 / no room for a new process
  3091                              <1> sysfork_err:
  3092 00003338 E9A4FDFFFF          <1> 	jmp	error
  3093                              <1> sysfork_2: ; 1:
  3094 0000333D E89FF0FFFF          <1> 	call	allocate_page
  3095                              <1> 	;jc	error
  3096                              <1> 	; 01/02/2022
  3097 00003342 72F4                <1> 	jc	short sysfork_err
  3098 00003344 50                  <1> 	push	eax  ; UPAGE (user structure page) address
  3099                              <1> 	; Retro UNIX 386 v1 modification!
  3100 00003345 E88EF2FFFF          <1> 	call	duplicate_page_dir
  3101                              <1> 		; EAX = New page directory 
  3102 0000334A 7308                <1> 	jnc	short sysfork_3
  3103 0000334C 58                  <1> 	pop	eax  ; UPAGE (user structure page) address
  3104 0000334D E855F2FFFF          <1> 	call 	deallocate_page
  3105                              <1> 	;jmp	error
  3106                              <1> 	; 01/02/2022
  3107 00003352 EBE4                <1> 	jmp	short sysfork_err
  3108                              <1> sysfork_3:
  3109                              <1> 	; Retro UNIX 386 v1 modification !
  3110 00003354 56                  <1> 	push	esi
  3111 00003355 E8B3110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3112                              <1> 		      ; and interrupt return components (for IRET)
  3113 0000335A 8705[53650000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3114 00003360 A3[57650000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3115 00003365 5E                  <1> 	pop	esi
  3116 00003366 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3117                              <1> 		; [u.usp] = esp
  3118 00003367 89F7                <1> 	mov	edi, esi
  3119                              <1> 	;shl	di, 2
  3120                              <1> 	; 12/02/2022
  3121 00003369 C1E702              <1> 	shl	edi, 2
  3122 0000336C 8987[80620000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3123 00003372 A3[4A650000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3124                              <1> 	; 28/08/2015
  3125 00003377 0FB605[49650000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3126                              <1> 		; movb u.uno,-(sp) / save parent process number
  3127 0000337E 89C7                <1> 	mov	edi, eax
  3128 00003380 50                  <1>         push	eax ; ** 
  3129 00003381 8A87[53620000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3130                              <1> 	; 18/09/2015
  3131 00003387 8886[53620000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3132                              <1> 	; 26/02/2022 (p.waitc is not used)
  3133                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3134                              <1> 	; 25/02/2022 (BugFix)
  3135                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3136                              <1> 	;			   ; ah - reset child's wait channel	
  3137 0000338D 89F0                <1> 	mov	eax, esi
  3138 0000338F A2[49650000]        <1> 	mov	[u.uno], al ; child process number
  3139                              <1> 		;movb r1,u.uno / set child process number to r1
  3140 00003394 FE86[73620000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3141                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3142                              <1> 				  ; / process to active status
  3143                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3144                              <1> 			      ; / control tty buffer in r2
  3145                              <1>                 ; beq 2f / branch, if no such tty assigned
  3146                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3147                              <1> 	; 2:
  3148 0000339A 53                  <1> 	push	ebx  ; * return address for the child process
  3149                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3150                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3151                              <1> 		; mov $runq+4,r2
  3152 0000339B E8C3110000          <1> 	call	putlu 
  3153                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3154                              <1> 			   ; / run queue
  3155                              <1> 	; 12/02/2022
  3156 000033A0 D1E6                <1> 	shl	esi, 1
  3157                              <1> 	;shl	si, 1
  3158                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3159                              <1> 		       ; / into p.pid table
  3160 000033A2 66FF05[EC640000]    <1> 	inc	word [mpid]
  3161                              <1> 		; inc mpid / increment m.pid; get a new process name
  3162 000033A9 66A1[EC640000]      <1> 	mov	ax, [mpid]
  3163 000033AF 668986[12620000]    <1> 	mov	[esi+p.pid-2], ax
  3164                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3165                              <1> 				    ; / in child process' name slot
  3166 000033B6 5A                  <1> 	pop	edx  ; * return address for the child process
  3167                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3168 000033B7 5B                  <1>   	pop	ebx  ; **
  3169                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3170                              <1> 		; movb (sp),r2 / put parent process number in r2
  3171                              <1> 	; 01/02/2022
  3172 000033B8 D0E3                <1> 	shl	bl, 1
  3173                              <1> 	;shl 	bx, 1
  3174                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3175                              <1> 	; ebx <= 32
  3176                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3177 000033BA 668B83[12620000]    <1> 	mov	ax, [ebx+p.pid-2]
  3178                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3179                              <1> 				   ; / process
  3180 000033C1 668986[32620000]    <1> 	mov	[esi+p.ppid-2], ax
  3181                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3182                              <1> 			  ; / in parent process slot for child
  3183 000033C8 A3[00650000]        <1> 	mov	[u.r0], eax	
  3184                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3185                              <1> 			     ; / at location where r0 was saved
  3186 000033CD 8B2D[F8640000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3187 000033D3 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3188                              <1> 			   ; * return address for the child process
  3189                              <1> 		; mov $sysret1,-(sp) /
  3190                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3191                              <1> 			      ; / user is swapped out
  3192                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3193                              <1> 	; 04/09/2015 - 01/09/2015
  3194                              <1> 	; [u.usp] = esp
  3195 000033D6 68[01310000]        <1> 	push	sysret ; ***
  3196 000033DB 8925[FC640000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3197                              <1> 			     ; (for child process)	
  3198 000033E1 31C0                <1> 	xor 	eax, eax
  3199 000033E3 66A3[30650000]      <1> 	mov 	[u.ttyp], ax ; 0
  3200                              <1> 	;
  3201 000033E9 E81F110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3202                              <1> 		;jsr r0,wswap / put child process out on drum
  3203                              <1> 		;jsr r0,unpack / unpack user stack
  3204                              <1> 		;mov u.usp,sp / restore user stack pointer
  3205                              <1> 		; tst (sp)+ / bump stack pointer
  3206                              <1> 	; Retro UNIX 386 v1 modification !
  3207 000033EE 58                  <1> 	pop	eax ; ***
  3208                              <1> 	;shl	bx, 1
  3209                              <1> 	; 01/02/2022
  3210 000033EF D0E3                <1> 	shl	bl, 1 
  3211                              <1> 		; ebx <= 64
  3212 000033F1 8B83[80620000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3213 000033F7 E83A110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3214                              <1> 		      ; registers and return address (for IRET)
  3215                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3216 000033FC 0FB705[EC640000]    <1>         movzx   eax, word [mpid]
  3217 00003403 A3[00650000]        <1> 	mov	[u.r0], eax
  3218                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3219                              <1> 			       ; / where r0 was saved
  3220                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3221                              <1> 			       ; / process return
  3222                              <1> 	;xor	ebx, ebx
  3223 00003408 31F6                <1> 	xor     esi, esi
  3224                              <1> 		;clr r1
  3225                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3226                              <1> 	      ; / opened by the parent process
  3227                              <1> 	; 01/09/2015
  3228                              <1> 	;xor	bh, bh
  3229                              <1> 	;mov 	bl, [esi+u.fp]
  3230 0000340A 8A86[06650000]      <1> 	mov 	al, [esi+u.fp]
  3231                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3232                              <1>         ;or	bl, bl
  3233 00003410 08C0                <1> 	or	al, al
  3234 00003412 740C                <1> 	jz	short sysfork_5	
  3235                              <1> 		; beq 2f / file has not been opened by parent, 
  3236                              <1> 		       ; / so branch
  3237 00003414 B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3238 00003416 F6E4                <1> 	mul	ah
  3239                              <1> 	;;movzx	ebx, ax
  3240                              <1> 	;mov	bx, ax
  3241 00003418 89C3                <1> 	mov	ebx, eax ; 12/02/2022
  3242                              <1> 	;shl	bx, 3
  3243                              <1> 		; asl r2 / multiply by 8
  3244                              <1>        		; asl r2 / to get index into fsp table
  3245                              <1>        		; asl r2
  3246 0000341A FE83[C2620000]      <1>   	inc     byte [ebx+fsp-2]
  3247                              <1> 		; incb fsp-2(r2) / increment number of processes
  3248                              <1> 			     ; / using file, because child will now be
  3249                              <1> 			     ; / using this file
  3250                              <1> sysfork_5: ; 2:
  3251 00003420 46                  <1>         inc     esi
  3252                              <1> 		; inc r1 / get next open file
  3253 00003421 6683FE0A            <1>         cmp     si, 10
  3254                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3255                              <1> 			    ; / can be opened
  3256 00003425 72E3                <1> 	jb	short sysfork_4	
  3257                              <1> 		; blt 1b / check next entry
  3258 00003427 E9D5FCFFFF          <1> 	jmp	sysret
  3259                              <1> 		; br sysret1
  3260                              <1> 
  3261                              <1> sysread: ; < read from file >
  3262                              <1> 	; 27/02/2022
  3263                              <1> 	; 01/02/2022
  3264                              <1> 	; 13/05/2015
  3265                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3266                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3267                              <1> 	;
  3268                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3269                              <1> 	; characters to be read. If finds the file from the file
  3270                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3271                              <1> 	; is returned from a successful open call (sysopen).
  3272                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3273                              <1> 	; is read into core via 'readi'.
  3274                              <1> 	;
  3275                              <1> 	; Calling sequence:
  3276                              <1> 	;	sysread; buffer; nchars
  3277                              <1> 	; Arguments:
  3278                              <1> 	;	buffer - location of contiguous bytes where 
  3279                              <1> 	;		 input will be placed.
  3280                              <1> 	;	nchars - number of bytes or characters to be read.
  3281                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3282                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3283                              <1> 	; ...............................................................
  3284                              <1> 	;				
  3285                              <1> 	; Retro UNIX 8086 v1 modification: 
  3286                              <1> 	;       'sysread' system call has three arguments; so,
  3287                              <1> 	;	* 1st argument, file descriptor is in BX register
  3288                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3289                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3290                              <1> 	;
  3291                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3292                              <1> 	;	to the user with number of bytes read. 
  3293                              <1> 	;
  3294 0000342C E840000000          <1> 	call	rw1
  3295                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3296                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3297                              <1>        	; 27/02/2022
  3298 00003431 7239                <1> 	jc	short sysread_err
  3299 00003433 F6C480              <1> 	test	ah, 80h
  3300                              <1> 		; tst r1 / negative i-number?
  3301                              <1> 	;jnz	error
  3302                              <1> 		; ble error1 / yes, error 1 to read
  3303                              <1> 			   ; / it should be positive
  3304                              <1> 	; 01/02/2022
  3305                              <1> 	;jnz	short rw_error
  3306                              <1> 	;27/02/2022
  3307 00003436 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3308                              <1> 	;
  3309 00003438 E88D150000          <1> 	call	readi
  3310                              <1> 		; jsr r0,readi / read data into core
  3311 0000343D EB14                <1> 	jmp	short rw0
  3312                              <1> 		; br 1f
  3313                              <1> 
  3314                              <1> syswrite: ; < write to file >
  3315                              <1> 	; 27/02/2022
  3316                              <1> 	; 01/02/2022
  3317                              <1> 	; 13/05/2015
  3318                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3319                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3320                              <1> 	;
  3321                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3322                              <1> 	; and the number of characters to write. If finds the file
  3323                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3324                              <1> 	; descriptor is returned from a successful open or create call
  3325                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3326                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3327                              <1> 	;
  3328                              <1> 	; Calling sequence:
  3329                              <1> 	;	syswrite; buffer; nchars
  3330                              <1> 	; Arguments:
  3331                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3332                              <1> 	;	nchars - number of characters to be written.
  3333                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3334                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3335                              <1> 	; ...............................................................
  3336                              <1> 	;				
  3337                              <1> 	; Retro UNIX 8086 v1 modification: 
  3338                              <1> 	;       'syswrite' system call has three arguments; so,
  3339                              <1> 	;	* 1st argument, file descriptor is in BX register
  3340                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3341                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3342                              <1> 	;
  3343                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3344                              <1> 	;	to the user with number of bytes written. 
  3345                              <1> 	;
  3346 0000343F E82D000000          <1> 	call	rw1
  3347                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3348                              <1> 		; jsr r0,rw1 / get i-number in r1 of file to write
  3349                              <1> 	; 01/02/2022
  3350                              <1> 	;jnc	short syswrite_1
  3351                              <1> ;rw_error:
  3352                              <1> 	;jmp	error
  3353                              <1> 	; 27/02/2022
  3354 00003444 7226                <1> 	jc	short short syswrite_err
  3355                              <1> syswrite_1:
  3356 00003446 F6C480              <1>         test	ah, 80h
  3357                              <1> 		; tst r1 / positive i-number ?
  3358 00003449 7417                <1>         jz	short rw3 ; 13/05/2015
  3359                              <1> 	;jz	error
  3360                              <1> 		; bge error1 / yes, error 1 
  3361                              <1> 			   ; / negative i-number means write
  3362 0000344B 66F7D8              <1> 	neg	ax
  3363                              <1> 		; neg r1 / make it positive
  3364 0000344E E869170000          <1> 	call	writei
  3365                              <1>         	; jsr r0,writei / write data
  3366                              <1> rw0: ; 1:
  3367 00003453 A1[28650000]        <1>         mov	eax, [u.nread]
  3368 00003458 A3[00650000]        <1> 	mov	[u.r0], eax
  3369                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3370                              <1> 				  ; / into (u.r0)
  3371 0000345D E99FFCFFFF          <1> 	jmp	sysret
  3372                              <1>         	; br sysret1
  3373                              <1> rw3: 
  3374                              <1> 	; 13/05/2015
  3375 00003462 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3375 0000346A 0000                <1>
  3376                              <1> 	;stc
  3377                              <1> 	;retn
  3378                              <1> 	; 27/02/2022 (BugFix)
  3379                              <1> sysread_err:
  3380                              <1> syswrite_err:
  3381 0000346C E970FCFFFF          <1> 	jmp	error
  3382                              <1> 
  3383                              <1> rw1:	
  3384                              <1> 	; 14/05/2015
  3385                              <1> 	; 13/05/2015
  3386                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3387                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3388                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3389                              <1> 	;
  3390                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3391                              <1> 				;(in the user's virtual memory space)
  3392                              <1> 	;mov	[u.count], edx 
  3393                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3394                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3395                              <1> 	;;mov	eax, ebx ; file descriptor
  3396                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3397                              <1> 		             ; / (index to u.fp table) in r1
  3398                              <1> 	; 13/05/2015
  3399 00003471 C705[00650000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3399 00003479 0000                <1>
  3400                              <1> 	;
  3401                              <1> 	;; call	getf
  3402                              <1>         ; eBX = File descriptor
  3403 0000347B E82E0B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3404                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3405                              <1> 	; AX = I-number of the file ; negative i-number means write
  3406                              <1> 	; 13/05/2015
  3407 00003480 6683F801            <1> 	cmp 	ax, 1
  3408 00003484 7217                <1> 	jb	short rw2
  3409                              <1> 	;
  3410 00003486 890D[20650000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3411                              <1> 				;(in the user's virtual memory space)
  3412 0000348C 8915[24650000]      <1> 	mov	[u.count], edx 
  3413                              <1> 	; 14/05/2015
  3414 00003492 C705[4F650000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3414 0000349A 0000                <1>
  3415 0000349C C3                  <1> 	retn
  3416                              <1>         	; rts r0
  3417                              <1> rw2:
  3418                              <1> 	; 13/05/2015
  3419 0000349D C705[4F650000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3419 000034A5 0000                <1>
  3420 000034A7 C3                  <1> 	retn
  3421                              <1> 
  3422                              <1> sysopen: ;<open file>
  3423                              <1> 	; 12/02/2022
  3424                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3425                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3426                              <1> 	;
  3427                              <1> 	; 'sysopen' opens a file in following manner:
  3428                              <1> 	;    1) The second argument in a sysopen says whether to
  3429                              <1> 	;	open the file ro read (0) or write (>0).
  3430                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3431                              <1> 	;    3) The file is opened by 'iopen'.
  3432                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3433                              <1> 	;	and the user's open file list - u.fp.
  3434                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3435                              <1> 	;	b) An entry for the file is created in the fsp table.
  3436                              <1> 	;	c) The number of this entry is put on u.fp list.
  3437                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3438                              <1> 	;	   to by u.r0.
  3439                              <1> 	;
  3440                              <1> 	; Calling sequence:
  3441                              <1> 	;	sysopen; name; mode
  3442                              <1> 	; Arguments:
  3443                              <1> 	;	name - file name or path name
  3444                              <1> 	;	mode - 0 to open for reading
  3445                              <1> 	;	       1 to open for writing
  3446                              <1> 	; Inputs: (arguments)
  3447                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3448                              <1> 	;		  is put into r0's location on the stack.	
  3449                              <1> 	; ...............................................................
  3450                              <1> 	;				
  3451                              <1> 	; Retro UNIX 8086 v1 modification: 
  3452                              <1> 	;       'sysopen' system call has two arguments; so,
  3453                              <1> 	;	* 1st argument, name is pointed to by BX register
  3454                              <1> 	;	* 2nd argument, mode is in CX register
  3455                              <1> 	;
  3456                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3457                              <1> 	;	to the user with the file descriptor/number 
  3458                              <1> 	;	(index to u.fp list).
  3459                              <1> 	;
  3460                              <1> 	;call	arg2
  3461                              <1> 	; * name - 'u.namep' points to address of file/path name
  3462                              <1> 	;          in the user's program segment ('u.segmnt')
  3463                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3464                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3465                              <1> 	;          which is on top of stack.
  3466                              <1> 	;
  3467                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3468                              <1> 	;
  3469                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3470                              <1> 
  3471 000034A8 891D[18650000]      <1> 	mov	[u.namep], ebx
  3472                              <1> 	;push	cx
  3473 000034AE 51                  <1> 	push	ecx ; 12/02/2022
  3474 000034AF E82D0B0000          <1> 	call	namei
  3475                              <1> 		; jsr r0,namei / i-number of file in r1
  3476                              <1>      	;and	ax, ax
  3477                              <1> 	;jz	error ; File not found
  3478 000034B4 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3479                              <1> 	;jc	error ; 27/05/2013
  3480                              <1> 		; br  error2 / file not found
  3481                              <1>    	;pop	dx ; mode
  3482                              <1> 	;push	dx
  3483                              <1> 	; 12/02/2022
  3484                              <1> 	;pop	edx ; * ; mode
  3485                              <1> 	;push	edx ; *
  3486 000034B6 8B1424              <1> 	mov	edx, [esp] ; *
  3487                              <1> 	; edx = open mode (0 or 1)
  3488                              <1> 	;or	dx, dx
  3489 000034B9 08D2                <1> 	or	dl, dl
  3490                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3491                              <1> 		         ; / 0 means, open for read)
  3492 000034BB 7403                <1> 	jz	short sysopen_0
  3493                              <1> 		; beq 1f / yes, leave i-number positive
  3494                              <1> syscreat_0: 
  3495                              <1> 	; 12/02/2022 (v1.0, 2022) ; 27/12/2015 (v1.1)
  3496 000034BD 66F7D8              <1> 	neg	ax
  3497                              <1>         	; neg r1 / open for writing so make i-number negative
  3498                              <1> sysopen_0: ;1:
  3499 000034C0 E8951B0000          <1> 	call	iopen
  3500                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3501 000034C5 5A                  <1> 	pop	edx ; * ; mode ; 12/02/2022
  3502                              <1> 	;and	dx, dx
  3503 000034C6 20D2                <1> 	and	dl, dl
  3504                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3505 000034C8 7403                <1> 	jz	short sysopen_2
  3506                              <1>         	; beq op1 / is open for read op1
  3507                              <1> sysopen_1: ;op0:
  3508 000034CA 66F7D8              <1> 	neg	ax
  3509                              <1>         	; neg r1 
  3510                              <1> 		     ;/ make i-number positive if open for writing [???]
  3511                              <1> 	;; NOTE: iopen always make i-number positive.
  3512                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3513                              <1> sysopen_2: ;op1:
  3514 000034CD 31F6                <1>         xor     esi, esi
  3515                              <1>         	; clr r2 / clear registers
  3516 000034CF 31DB                <1>         xor     ebx, ebx
  3517                              <1> 		; clr r3
  3518                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3519 000034D1 389E[06650000]      <1>         cmp     [esi+u.fp], bl ; 0
  3520                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3521 000034D7 7625                <1>         jna	short sysopen_4
  3522                              <1> 		; beq 1f / if byte in list is 0 branch
  3523 000034D9 46                  <1>         inc     esi
  3524                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3525 000034DA 6683FE0A            <1>         cmp     si, 10
  3526                              <1> 		; cmp r2,$10. / reached end of list?
  3527 000034DE 72F1                <1> 	jb	short sysopen_3
  3528                              <1> 		; blt 1b / no, go back
  3529                              <1> toomanyf:
  3530                              <1> 	; 14/05/2015
  3531 000034E0 C705[4F650000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3531 000034E8 0000                <1>
  3532 000034EA E9F2FBFFFF          <1> 	jmp	error
  3533                              <1>         	; br error2 / yes, error (no files open)
  3534                              <1> fnotfound: 
  3535                              <1> 	; 14/05/2015
  3536 000034EF C705[4F650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3536 000034F7 0000                <1>
  3537 000034F9 E9E3FBFFFF          <1> 	jmp	error
  3538                              <1> 
  3539                              <1> sysopen_4: ; 1:
  3540 000034FE 6683BB[C4620000]00  <1>         cmp     word [ebx+fsp], 0
  3541                              <1> 		; tst fsp(r3) / scan fsp entries
  3542 00003506 7610                <1>         jna     short sysopen_5
  3543                              <1> 		; beq 1f / if 0 branch
  3544                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3545 00003508 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3546                              <1> 		; add $8.,r3 / add 8 to r3 
  3547                              <1> 			; / to bump it to next entry mfsp table
  3548 0000350C 6681FBF401          <1>         cmp     bx, nfiles*10
  3549                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3550 00003511 72EB                <1> 	jb	short sysopen_4
  3551                              <1>        		; blt 1b / no, back
  3552 00003513 E9C9FBFFFF          <1> 	jmp	error
  3553                              <1>         	; br error2 / yes, error
  3554                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3555 00003518 668983[C4620000]    <1>         mov     [ebx+fsp], ax
  3556                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3557                              <1> 			; / into next available entry in fsp table,
  3558                              <1> 	; 12/02/2022
  3559                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3560                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3561                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3562                              <1> 	;xor	edi, edi
  3563                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3564                              <1> 	;	; clr fsp+4(r3)
  3565                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3566                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3567 0000351F 31C0                <1> 	xor	eax, eax
  3568 00003521 8983[C8620000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3569 00003527 668983[CC620000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3570                              <1> 
  3571 0000352E 66A1[E4640000]      <1> 	mov	ax, [cdev]
  3572 00003534 668983[C6620000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3573                              <1> 
  3574 0000353B 89D8                <1>   	mov	eax, ebx
  3575 0000353D B30A                <1> 	mov	bl, 10
  3576 0000353F F6F3                <1> 	div	bl 
  3577                              <1> 		; asr r3
  3578                              <1> 		; asr r3 / divide by 8 
  3579                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3580 00003541 FEC0                <1> 	inc	al
  3581                              <1>         	; inc r3 / add 1 to get fsp entry number
  3582 00003543 8886[06650000]      <1>         mov     [esi+u.fp], al
  3583                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3584                              <1> 			; / next available slot in u.fp list
  3585 00003549 8935[00650000]      <1>         mov     [u.r0], esi
  3586                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3587                              <1> 			     ; / into r0 loc on stack
  3588 0000354F E9ADFBFFFF          <1>         jmp	sysret
  3589                              <1> 		; br sysret2
  3590                              <1> 
  3591                              <1> 	;
  3592                              <1> 	; 'fsp' table (10 bytes/entry)
  3593                              <1> 	; bit 15				   bit 0
  3594                              <1> 	; ---|-------------------------------------------
  3595                              <1> 	; r/w|		i-number of open file
  3596                              <1> 	; ---|-------------------------------------------
  3597                              <1> 	;		   device number
  3598                              <1> 	; -----------------------------------------------
  3599                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3600                              <1> 	; -----------------------------------------------
  3601                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3602                              <1> 	; ----------------------|------------------------
  3603                              <1> 	;  flag that says file 	| number of processes
  3604                              <1> 	;   has been deleted	| that have file open 
  3605                              <1> 	; ----------------------|------------------------
  3606                              <1> 	;
  3607                              <1> 
  3608                              <1> syscreat: ; < create file >
  3609                              <1> 	; 12/02/2022
  3610                              <1> 	; 01/02/2022
  3611                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3612                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3613                              <1> 	;
  3614                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3615                              <1> 	; u.namep points to name of the file and mode is put
  3616                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3617                              <1> 	; If the file aready exists, it's mode and owner remain 
  3618                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3619                              <1> 	; did not exist, an i-node is created with the new mode via
  3620                              <1> 	; 'maknod' whether or not the file already existed, it is
  3621                              <1> 	; open for writing. The fsp table is then searched for a free
  3622                              <1> 	; entry. When a free entry is found, proper data is placed
  3623                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3624                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3625                              <1> 	; is put in the user's r0. 			
  3626                              <1> 	;
  3627                              <1> 	; Calling sequence:
  3628                              <1> 	;	syscreate; name; mode
  3629                              <1> 	; Arguments:
  3630                              <1> 	;	name - name of the file to be created
  3631                              <1> 	;	mode - mode of the file to be created
  3632                              <1> 	; Inputs: (arguments)
  3633                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3634                              <1> 	;		   (the file descriptor of new file)
  3635                              <1> 	; ...............................................................
  3636                              <1> 	;				
  3637                              <1> 	; Retro UNIX 8086 v1 modification: 
  3638                              <1> 	;       'syscreate' system call has two arguments; so,
  3639                              <1> 	;	* 1st argument, name is pointed to by BX register
  3640                              <1> 	;	* 2nd argument, mode is in CX register
  3641                              <1> 	;
  3642                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3643                              <1> 	;	to the user with the file descriptor/number 
  3644                              <1> 	;	(index to u.fp list).
  3645                              <1> 	;
  3646                              <1> 	;call	arg2
  3647                              <1> 	; * name - 'u.namep' points to address of file/path name
  3648                              <1> 	;          in the user's program segment ('u.segmnt')
  3649                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3650                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3651                              <1> 	;          which is on top of stack.
  3652                              <1> 	;
  3653                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3654                              <1> 			    ; / on stack
  3655 00003554 891D[18650000]      <1> 	mov	[u.namep], ebx ; file name address
  3656                              <1> 	;push	cx ; mode
  3657                              <1> 	; 01/02/2022
  3658 0000355A 51                  <1> 	push	ecx ; mode
  3659 0000355B E8810A0000          <1> 	call 	namei        	
  3660                              <1> 		; jsr r0,namei / get the i-number
  3661                              <1>         ;and	ax, ax
  3662                              <1> 	;jz	short syscreat_2	       	
  3663 00003560 721B                <1> 	jc	short syscreat_2
  3664                              <1> 		; br  2f / if file doesn't exist 2f
  3665                              <1> 	; 12/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18, 2022)
  3666                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3667 00003562 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3668                              <1>         ;jb	syscreat_0 ; yes
  3669                              <1> 	; 02/02/2022
  3670 00003566 7305                <1> 	jnb	short syscreat_1
  3671 00003568 E950FFFFFF          <1> 	jmp	syscreat_0
  3672                              <1> syscreat_1:
  3673 0000356D 66F7D8              <1> 	neg 	ax
  3674                              <1>         	; neg r1 / if file already exists make i-number 
  3675                              <1> 		       ; / negative (open for writing)
  3676 00003570 E8E51A0000          <1> 	call	iopen
  3677                              <1>         	; jsr r0,iopen /
  3678 00003575 E8A8130000          <1> 	call	itrunc
  3679                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3680                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3681                              <1> 	; 01/02/2022
  3682 0000357A 59                  <1> 	pop	ecx ; mode
  3683                              <1> 	; 12/02/2022
  3684 0000357B EB0E                <1> 	jmp	short syscreat_3
  3685                              <1>         ;jmp	sysopen_1
  3686                              <1>         	; br op0
  3687                              <1> syscreat_2: ; 2: / file doesn't exist
  3688                              <1> 	; 01/02/2022
  3689 0000357D 58                  <1> 	pop	eax ; mode
  3690                              <1> 	;pop	ax
  3691                              <1>         	; mov (sp)+,r1 / put the mode in r1
  3692 0000357E 30E4                <1> 	xor	ah, ah	
  3693                              <1>         	; bic $!377,r1 / clear upper byte
  3694 00003580 E86D0D0000          <1> 	call 	maknod
  3695                              <1>         	; jsr r0,maknod / make an i-node for this file
  3696 00003585 66A1[32650000]      <1> 	mov	ax, [u.dirbuf]
  3697                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3698                              <1> 			        ; / for this new file in r1
  3699                              <1> syscreat_3:
  3700 0000358B E93AFFFFFF          <1>         jmp     sysopen_1
  3701                              <1>         	; br op0 / open the file
  3702                              <1> 
  3703                              <1> sysmkdir: ; < make directory >
  3704                              <1> 	; 01/02/2022
  3705                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3706                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3707                              <1> 	;
  3708                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3709                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3710                              <1> 	; The special entries '.' and '..' are not present.
  3711                              <1> 	; Errors are indicated if the directory already exists or		
  3712                              <1> 	; user is not the super user. 
  3713                              <1> 	;
  3714                              <1> 	; Calling sequence:
  3715                              <1> 	;	sysmkdir; name; mode
  3716                              <1> 	; Arguments:
  3717                              <1> 	;	name - points to the name of the directory
  3718                              <1> 	;	mode - mode of the directory
  3719                              <1> 	; Inputs: (arguments)
  3720                              <1> 	; Outputs: -
  3721                              <1> 	;    (sets 'directory' flag to 1; 
  3722                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3723                              <1> 	; ...............................................................
  3724                              <1> 	;				
  3725                              <1> 	; Retro UNIX 8086 v1 modification: 
  3726                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3727                              <1> 	;	* 1st argument, name is pointed to by BX register
  3728                              <1> 	;	* 2nd argument, mode is in CX register
  3729                              <1> 		
  3730                              <1> ; / make a directory
  3731                              <1> 	
  3732                              <1> 	;call	arg2
  3733                              <1> 	; * name - 'u.namep' points to address of file/path name
  3734                              <1> 	;          in the user's program segment ('u.segmnt')
  3735                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3736                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3737                              <1> 	;          which is on top of stack.
  3738                              <1> 
  3739                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3740                              <1> 			    ; / on stack
  3741 00003590 891D[18650000]      <1> 	mov	[u.namep], ebx
  3742                              <1> 	;push	cx ; mode
  3743                              <1> 	; 01/02/2022
  3744 00003596 51                  <1> 	push	ecx ; mode
  3745 00003597 E8450A0000          <1> 	call	namei
  3746                              <1>         	; jsr r0,namei / get the i-number
  3747                              <1>         	;     br .+4 / if file not found branch around error
  3748                              <1>         ;xor 	ax, ax
  3749                              <1> 	;jnz	error
  3750 0000359C 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3751                              <1> 	;jnc	error	
  3752                              <1> 		; br  error2 / directory already exists (error)
  3753 0000359E 803D[46650000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3754                              <1>         	;tstb u.uid / is user the super user
  3755                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3756                              <1> 	;;jna	error
  3757                              <1> 	; 01/02/2022 (BugFix)
  3758 000035A5 7721                <1> 	ja	short dir_access_err
  3759                              <1>         	;bne error2 / no, not allowed
  3760                              <1> 	;pop	ax
  3761                              <1> 	; 01/02/2022
  3762 000035A7 58                  <1> 	pop	eax ; mode
  3763                              <1>         	;mov (sp)+,r1 / put the mode in r1
  3764 000035A8 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3765                              <1>         	;bic $!317,r1 / all but su and ex
  3766                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3767 000035AC 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3768                              <1>         	;bis $40000,r1 / directory flag
  3769 000035AF E83E0D0000          <1> 	call	maknod
  3770                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3771                              <1> sysclose_sysret: ; 01/02/2022
  3772 000035B4 E948FBFFFF          <1> 	jmp	sysret
  3773                              <1>         	;br sysret2 /
  3774                              <1> dir_exists:
  3775                              <1> 	; 14/05/2015
  3776 000035B9 C705[4F650000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3776 000035C1 0000                <1>
  3777 000035C3 E919FBFFFF          <1> 	jmp	error
  3778                              <1> dir_access_err:
  3779                              <1> 	; 14/05/2015
  3780 000035C8 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3780 000035D0 0000                <1>
  3781 000035D2 E90AFBFFFF          <1> 	jmp	error
  3782                              <1> 
  3783                              <1> sysclose: ;<close file>
  3784                              <1> 	; 01/02/2022
  3785                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3786                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3787                              <1> 	;
  3788                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3789                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3790                              <1> 	; is put in r1 and 'fclose' is called.
  3791                              <1> 	;
  3792                              <1> 	; Calling sequence:
  3793                              <1> 	;	sysclose
  3794                              <1> 	; Arguments:
  3795                              <1> 	;	-  
  3796                              <1> 	; Inputs: *u.r0 - file descriptor
  3797                              <1> 	; Outputs: -
  3798                              <1> 	; ...............................................................
  3799                              <1> 	;				
  3800                              <1> 	; Retro UNIX 8086 v1 modification:
  3801                              <1> 	;	 The user/application program puts file descriptor
  3802                              <1> 	;        in BX register as 'sysclose' system call argument.
  3803                              <1> 	; 	 (argument transfer method 1)
  3804                              <1> 
  3805                              <1> 	; / close the file
  3806                              <1> 	
  3807 000035D7 89D8                <1> 	mov 	eax, ebx
  3808 000035D9 E88D090000          <1> 	call 	fclose
  3809                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3810                              <1> 		; jsr r0,fclose / close the file
  3811                              <1>                	; br error2 / unknown file descriptor
  3812                              <1> 		; br sysret2
  3813                              <1> 	; 14/05/2015
  3814                              <1> 	;jnc	sysret
  3815                              <1> 	; 01/02/2022
  3816 000035DE 73D4                <1> 	jnc	short sysclose_sysret
  3817 000035E0 C705[4F650000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3817 000035E8 0000                <1>
  3818 000035EA E9F2FAFFFF          <1> 	jmp	error
  3819                              <1> 
  3820                              <1> sysemt:
  3821                              <1> 	; 23/02/2022
  3822                              <1> 	; 01/02/2022
  3823                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3824                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3825                              <1> 	;
  3826                              <1> 	; Retro UNIX 8086 v1 modification: 
  3827                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3828                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3829                              <1> 	;
  3830                              <1> 	; Retro UNIX 8086 v1 feature only!
  3831                              <1> 	;	Using purpose: Kernel will start without time-out
  3832                              <1> 	;	(internal clock/timer) functionality.
  3833                              <1> 	;	Then etc/init will enable clock/timer for
  3834                              <1> 	;	multi tasking. (Then it will not be disabled again
  3835                              <1> 	;	except hardware reset/restart.)
  3836                              <1> 
  3837 000035EF 803D[46650000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3838                              <1> 	;;ja	error
  3839                              <1> 	;ja	badsys ; 14/05/2015
  3840                              <1> 	; 01/02/2022
  3841                              <1> 	;jna	short emt_0
  3842                              <1> 	;jmp	badsys
  3843 000035F6 773A                <1> 	ja	short sysilgins ; jmp badsys
  3844                              <1> emt_0:
  3845 000035F8 FA                  <1> 	cli
  3846 000035F9 21DB                <1> 	and	ebx, ebx
  3847 000035FB 7429                <1> 	jz	short emt_2
  3848                              <1> 	; Enable multi tasking -time sharing-
  3849 000035FD B8[AB450000]        <1> 	mov	eax, clock ; enable multi tasking clock/timer
  3850                              <1> 	; 23/02/2022
  3851 00003602 BA[430A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3852                              <1> emt_1:
  3853 00003607 A3[09070000]        <1> 	mov	[x_timer], eax
  3854                              <1> 	; 23/02/2022 (Temporary)
  3855 0000360C 8915[0D070000]      <1> 	mov	[x_rtci], edx
  3856 00003612 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3857 00003614 E853020000          <1> 	call	wttyc  ; clear video page
  3858 00003619 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3859 0000361B E84C020000          <1> 	call	wttyc  ; clear video page
  3860                              <1> 	;
  3861 00003620 FB                  <1> 	sti
  3862 00003621 E9DBFAFFFF          <1> 	jmp	sysret
  3863                              <1> emt_2:
  3864                              <1> 	; Disable multi tasking -time sharing-
  3865 00003626 B8[15070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3866                              <1> 	; 23/02/2022
  3867 0000362B BA[4A0A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3868                              <1> 	;
  3869 00003630 EBD5                <1> 	jmp	short emt_1
  3870                              <1> 
  3871                              <1> 	; Original UNIX v1 'sysemt' routine
  3872                              <1> ;sysemt:
  3873                              <1>         ;
  3874                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3875                              <1> 			 ; / in loc 30
  3876                              <1>         ;cmp    30,$core / was the argument a lower address 
  3877                              <1> 			; / than core
  3878                              <1>         ;blo    1f / yes, rtssym
  3879                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3880                              <1> 			; / and less than "ecore"
  3881                              <1>         ;blo    2f / yes, sysret2
  3882                              <1> ;1:
  3883                              <1>         ;mov    $rtssym,30
  3884                              <1> ;2:
  3885                              <1>         ;br     sysret2
  3886                              <1> 
  3887                              <1> 	; 01/02/2022
  3888                              <1> sysilgins:
  3889                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3890                              <1> 	; 03/06/2013
  3891                              <1> 	; Retro UNIX 8086 v1 modification: 
  3892                              <1> 	;	not a valid system call ! (not in use)
  3893                              <1> 	;
  3894 00003632 E953FBFFFF          <1> 	jmp	badsys
  3895                              <1> 	;jmp	error
  3896                              <1> 	;;jmp 	sysret
  3897                              <1> 
  3898                              <1> 	; Original UNIX v1 'sysemt' routine
  3899                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3900                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3901                              <1> 			  ;/ put it in loc 8.,
  3902                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3903                              <1> 		       ; / trap address
  3904                              <1>         ;blo    1f / is the address a user core address?  
  3905                              <1> 		; / yes, go to 2f
  3906                              <1>         ;cmp    10,$ecore
  3907                              <1>         ;blo    2f
  3908                              <1> ;1:
  3909                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3910                              <1> 		    ; / instruction trap address for the system
  3911                              <1> ;2:
  3912                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3913                              <1> 
  3914                              <1> sysmdate: ; < change the modification time of a file >
  3915                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3916                              <1> 	;	(ECX input)
  3917                              <1> 	; 01/02/2022
  3918                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3919                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3920                              <1> 	;
  3921                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3922                              <1> 	; file into core. The user is checked if he is the owner 
  3923                              <1> 	; or super user. If he is neither an error occurs.
  3924                              <1> 	; 'setimod' is then called to set the i-node modification
  3925                              <1> 	; byte and the modification time, but the modification time
  3926                              <1> 	; is overwritten by whatever get put on the stack during
  3927                              <1> 	; a 'systime' system call. This calls are restricted to
  3928                              <1> 	; the super user.		
  3929                              <1> 	;
  3930                              <1> 	; Calling sequence:
  3931                              <1> 	;	sysmdate; name
  3932                              <1> 	; Arguments:
  3933                              <1> 	;	name - points to the name of file
  3934                              <1> 	; Inputs: (arguments)
  3935                              <1> 	; Outputs: -
  3936                              <1> 	; ...............................................................
  3937                              <1> 	;				
  3938                              <1> 	; Retro UNIX 8086 v1 modification: 
  3939                              <1> 	;	 The user/application program puts address 
  3940                              <1> 	;	 of the file name in BX register 
  3941                              <1> 	;	 as 'sysmdate' system call argument.
  3942                              <1> 	;
  3943                              <1> ; / change the modification time of a file
  3944                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3945 00003637 891D[18650000]      <1>         mov	[u.namep], ebx
  3946                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3947 0000363D 890D[80610000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3948 00003643 E899090000          <1> 	call	namei
  3949                              <1> 		; jsr r0,namei / get its i-number
  3950                              <1> 	;;jc	error       
  3951                              <1> 		; br error2 / no, such file
  3952                              <1> 	;jc	fnotfound ; file not found !
  3953                              <1> 	; 01/02/2022
  3954 00003648 7305                <1> 	jnc	short mdate_0
  3955 0000364A E9A0FEFFFF          <1> 	jmp	fnotfound
  3956                              <1> mdate_0:
  3957 0000364F E8A2110000          <1> 	call	iget
  3958                              <1> 		; jsr r0,iget / get i-node into core
  3959 00003654 A0[46650000]        <1> 	mov	al, [u.uid]
  3960 00003659 3A05[F7610000]      <1> 	cmp	al, [i.uid]
  3961                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  3962 0000365F 7413                <1> 	je	short mdate_1
  3963                              <1>         	; beq 1f / yes
  3964 00003661 20C0                <1> 	and	al, al
  3965                              <1> 		; tstb u.uid / no, is user the super user
  3966                              <1> 	;jnz	error
  3967                              <1> 		; bne error2 / no, error
  3968 00003663 740F                <1> 	jz	short mdate_1
  3969 00003665 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3969 0000366D 0000                <1>
  3970                              <1> sysstty_err:	; 01/02/2022
  3971 0000366F E96DFAFFFF          <1> 	jmp	error
  3972                              <1> mdate_1: ;1:
  3973 00003674 E887120000          <1> 	call	setimod
  3974                              <1>         	; jsr r0,setimod / fill in modification data,
  3975                              <1> 		               ; / time etc.
  3976 00003679 BE[80610000]        <1> 	mov	esi, p_time
  3977 0000367E BF[0E620000]        <1> 	mov	edi, i.mtim
  3978 00003683 A5                  <1> 	movsd
  3979                              <1> 		; mov 4(sp),i.mtim / move present time to
  3980                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  3981 00003684 E978FAFFFF          <1>         jmp	sysret
  3982                              <1> 		; br sysret2
  3983                              <1> 
  3984                              <1> 	; 01/02/2022
  3985                              <1> sysstty_err_s:
  3986 00003689 880D[00650000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  3987 0000368F EBDE                <1> 	jmp	short sysstty_err
  3988                              <1> 
  3989                              <1> sysstty: ; < set tty status and mode >
  3990                              <1> 	; 23/02/2022
  3991                              <1> 	; 22/02/2022
  3992                              <1> 	; 02/02/2022
  3993                              <1> 	; 01/02/2022 (clear screen)
  3994                              <1> 	; 17/11/2015
  3995                              <1> 	; 12/11/2015
  3996                              <1> 	; 29/10/2015
  3997                              <1> 	; 17/10/2015
  3998                              <1> 	; 13/10/2015
  3999                              <1> 	; 29/06/2015
  4000                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4001                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4002                              <1> 	;
  4003                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4004                              <1> 	; whose file descriptor is in (u.r0).
  4005                              <1> 	;
  4006                              <1> 	; Calling sequence:
  4007                              <1> 	;	sysstty; arg
  4008                              <1> 	; Arguments:
  4009                              <1> 	;	arg - address of 3 consequitive words that contain
  4010                              <1> 	;	      the source of status data	
  4011                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4012                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4013                              <1> 	; ...............................................................
  4014                              <1> 	;	
  4015                              <1> 	; Retro UNIX 8086 v1 modification: 
  4016                              <1> 	;	'sysstty' system call will set the tty
  4017                              <1> 	;	(clear keyboard buffer and set cursor position)
  4018                              <1> 	;	 in following manner:
  4019                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4020                              <1> 	;
  4021                              <1> 	; Inputs:
  4022                              <1> 	;	BX = 0 --> means
  4023                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4024                              <1> 	;	      set cursor position for console tty, only 
  4025                              <1> 	;	      CH will be ignored (char. will not be written)	
  4026                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4027                              <1> 	;	      set console tty for (current) process
  4028                              <1> 	;	      CL = tty number (0 to 9)
  4029                              <1> 	;	      (If CH = 0, character will not be written)
  4030                              <1> 	;          If CH > 0 (CL < FFh)	
  4031                              <1> 	;             CL = tty number (0 to 9)
  4032                              <1> 	;	      CH = character will be written
  4033                              <1> 	;	        at requested cursor position (in DX)	
  4034                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4035                              <1>   	;		(only tty number 0 to 7) 
  4036                              <1> 	;          DL = communication parameters (for serial ports) 
  4037                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4038                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4039                              <1> 	;			or set cursor position	
  4040                              <1> 	;	   DH = 0FFh -> DL is not valid
  4041                              <1> 	;		do not set serial port parameters 
  4042                              <1> 	;		or do not set cursor position
  4043                              <1> 	;
  4044                              <1> 	;	BX > 0 --> points to name of tty
  4045                              <1> 	;    	   CH > 0 -->
  4046                              <1> 	;		CH = character will be written in current 
  4047                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4048                              <1> 	;	     	or character will be sent to serial port
  4049                              <1> 	;	     	(for tty number 8 or 9)
  4050                              <1> 	;		CL = color of the character if tty number < 8.
  4051                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4052                              <1> 	;		set mode (tty 8 to 9) or 
  4053                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4054                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4055                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4056                              <1> 	;		(DL is not valid)
  4057                              <1> 	;	   DL = communication parameters 
  4058                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4059                              <1> 	;
  4060                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4061                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4062                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4063                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4064                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4065                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4066                              <1> 	;
  4067                              <1> 	; Outputs:
  4068                              <1> 	;	cf = 0 -> OK
  4069                              <1> 	;	     AL = tty number (0 to 9)
  4070                              <1> 	;	     AH = line status if tty number is 8 or 9
  4071                              <1> 	;	     AH = process number (of the caller) 	
  4072                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4073                              <1> 	;	     AH = FFh if the tty is locked 
  4074                              <1> 	;		  (owned by another process)
  4075                              <1> 	;	        = process number (of the caller) 
  4076                              <1> 	;		  (if < FFh and tty number < 8)
  4077                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4078                              <1> 	;	     AH = line status if tty number is 8 or 9
  4079                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4080                              <1> 	;	
  4081                              <1> 
  4082                              <1> 	; 27/06/2015 (32 bit modifications)
  4083                              <1> 	; 14/01/2014
  4084 00003691 31C0                <1> 	xor 	eax, eax
  4085 00003693 6648                <1> 	dec	ax ; 17/10/2015
  4086 00003695 A3[00650000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4087                              <1> 	;;;
  4088                              <1> 	; 01/02/2022
  4089 0000369A FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4090 0000369C 39C2                <1> 	cmp	edx, eax
  4091                              <1> 	;cmp	dx, ax ; 0FFFFh
  4092 0000369E 7521                <1> 	jne	short sysstty_18
  4093                              <1> 	; clear video page
  4094                              <1> 	; (CH must be 0)
  4095 000036A0 08ED                <1> 	or	ch, ch
  4096 000036A2 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4097 000036A4 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4098 000036A7 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4099 000036A9 20C9                <1> 	and	cl, cl
  4100 000036AB 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4101 000036AD 0FB635[49650000]    <1> 	movzx	esi, byte [u.uno]
  4102 000036B4 8A8E[53620000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4103 000036BA 80F907              <1> 	cmp	cl, 7
  4104 000036BD 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4105                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4106 000036BF FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4107                              <1> sysstty_18:
  4108 000036C1 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4109                              <1> 	; cl = video page (tty) number		
  4110                              <1> 	;;;
  4111 000036C3 21DB                <1> 	and	ebx, ebx
  4112                              <1> 	;jnz	sysstty_6
  4113                              <1> 	; 01/02/2022
  4114 000036C5 7405                <1> 	jz	short sysstty_19
  4115 000036C7 E9C2000000          <1> 	jmp	sysstty_6
  4116                              <1> sysstty_19:
  4117                              <1> 	; set console tty
  4118                              <1> 	; 29/10/2015
  4119                              <1> 	; 17/01/2014 
  4120 000036CC 80F909              <1> 	cmp	cl, 9
  4121 000036CF 7613                <1> 	jna	short sysstty_0
  4122                              <1> 	; 17/11/2015
  4123 000036D1 80F9FF              <1> 	cmp	cl, 0FFh
  4124 000036D4 7202                <1> 	jb	short sysstty_13
  4125 000036D6 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4126                              <1> sysstty_13:
  4127 000036D8 8A1D[49650000]      <1> 	mov	bl, [u.uno] ; process number
  4128 000036DE 8A8B[53620000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4129                              <1> sysstty_0:
  4130                              <1> 	; 29/06/2015
  4131                              <1> 	;push	dx
  4132                              <1> 	;push	cx
  4133                              <1> 	; 01/02/2022
  4134 000036E4 52                  <1> 	push	edx
  4135 000036E5 51                  <1> 	push	ecx
  4136 000036E6 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4137 000036E8 88C8                <1> 	mov	al, cl
  4138 000036EA A2[00650000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  4139 000036EF E8001A0000          <1> 	call	ottyp
  4140                              <1> 	; 01/02/2022
  4141 000036F4 59                  <1> 	pop	ecx
  4142 000036F5 5A                  <1> 	pop	edx
  4143                              <1> 	;pop	cx
  4144                              <1> 	;pop	dx
  4145                              <1> 	;
  4146 000036F6 7220                <1> 	jc	short sysstty_pd_err
  4147                              <1> 	;
  4148                              <1> 	; 22/02/2022 (Bug!, BugFix)
  4149                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4150                              <1> 	;
  4151 000036F8 80F908              <1> 	cmp	cl, 8
  4152 000036FB 720C                <1> 	jb	short sysstty_2
  4153                              <1> 	;
  4154 000036FD 80FEFF              <1> 	cmp	dh, 0FFh
  4155 00003700 7407                <1> 	je	short sysstty_2
  4156                              <1> 		; set communication parameters for serial ports
  4157                              <1> 
  4158                              <1> ; 01/02/2022
  4159                              <1> ;	; 29/10/2015
  4160                              <1> ;	mov	ah, dl ; communication parameters
  4161                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4162                              <1> ;		;			 THRE int + RDA int 
  4163                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4164                              <1> ;		;			 THRE int + RDA int 
  4165                              <1> ;	sub	al, al ; 0
  4166                              <1> ;	; 12/07/2014
  4167                              <1> ;	cmp	cl, 9
  4168                              <1> ;	jb	short sysstty_1
  4169                              <1> ;	inc	al
  4170                              <1> ;sysstty_1:
  4171                              <1> ;	; 01/02/2022
  4172                              <1> ;	push	ecx
  4173                              <1> ;	;push	cx
  4174                              <1> ;	; 29/06/2015	
  4175                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4176                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4177                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4178                              <1> ;	; 01/02/2022
  4179                              <1> ;	pop	ecx	
  4180                              <1> ;	;pop	cx
  4181                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4182                              <1> 
  4183                              <1> 	; 01/02/2022
  4184 00003702 E832010000          <1> 	call	sysstty_scp
  4185 00003707 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4186                              <1> 
  4187                              <1> sysstty_2:
  4188                              <1> 	; 17/01/2014
  4189 00003709 20ED                <1> 	and	ch, ch 	; set cursor position 
  4190                              <1> 			; or comm. parameters ONLY
  4191 0000370B 7527                <1> 	jnz	short sysstty_3
  4192                              <1> 	; 01/02/2022
  4193 0000370D 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4194 00003711 7214                <1> 	jb	short sysstty_20
  4195                              <1> 	; clear screen (video page)
  4196 00003713 E93D010000          <1> 	jmp	sysstty_14
  4197                              <1> 
  4198                              <1> sysstty_pd_err: ; 29/06/2015
  4199                              <1> 	; 'permission denied !' error
  4200 00003718 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4200 00003720 0000                <1>
  4201 00003722 E9BAF9FFFF          <1> 	jmp	error
  4202                              <1> 
  4203                              <1> sysstty_20:
  4204 00003727 0FB61D[49650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4205 0000372E 888B[53620000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4206                              <1> sysstty_3:
  4207                              <1> 	; 16/01/2014
  4208 00003734 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4209                              <1> 	; 17/11/2015
  4210 00003736 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4211 00003738 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4212                              <1> 	;jna	sysstty_9
  4213                              <1> 	; 01/02/2022
  4214 0000373A 7705                <1> 	ja	short sysstty_12
  4215 0000373C E9C7000000          <1> 	jmp	sysstty_9
  4216                              <1> 
  4217                              <1> sysstty_12:
  4218                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4219                              <1> 	; (Set specified serial port as console tty port)
  4220                              <1> 	; CH = character to be written
  4221                              <1> 	; 15/04/2014
  4222                              <1> 	; CH = 0 --> initialization only
  4223                              <1> 	; AL = character
  4224                              <1> 	; 26/06/2014
  4225 00003741 880D[4E650000]      <1> 	mov	[u.ttyn], cl
  4226                              <1> 	; 12/07/2014
  4227 00003747 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4228                              <1> 	; 02/02/2022
  4229 00003749 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4230 0000374B 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4231 0000374D FEC8                <1> 	dec	al  ; 1 -> 0	
  4232                              <1> 	;and	al, al
  4233 0000374F 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4234                              <1>  	; 04/07/2014
  4235 00003751 E8B41E0000          <1> 	call 	sndc
  4236                              <1> 	; 12/07/2014
  4237 00003756 EB0C                <1> 	jmp	short sysstty_5
  4238                              <1> 
  4239                              <1> sysstty_4:
  4240                              <1> 	; 12/07/2014
  4241                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4242 00003758 88E0                <1> 	mov	al, ah ; 29/06/2015
  4243 0000375A 2C08                <1> 	sub	al, 8
  4244                              <1> 	; 27/06/2015
  4245 0000375C E836F4FFFF          <1> 	call	sp_status ; get serial port status
  4246                              <1> 	; AL = Line status, AH = Modem status
  4247                              <1> 	; 12/11/2015
  4248 00003761 3C80                <1> 	cmp	al, 80h
  4249 00003763 F5                  <1> 	cmc
  4250                              <1> sysstty_5:
  4251 00003764 66A3[01650000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4252                              <1> 		; EAX bits 16-23 = modem status	
  4253 0000376A 9C                  <1> 	pushf
  4254 0000376B 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4255 0000376D A0[4E650000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4256 00003772 E8A01A0000          <1> 	call	cttyp
  4257 00003777 9D                  <1> 	popf
  4258                              <1> 	;jnc	sysret ; time out error 
  4259                              <1> 	; 01/02/2022
  4260 00003778 7205                <1> 	jc	short sysstty_tmout_err
  4261 0000377A E982F9FFFF          <1> 	jmp	sysret
  4262                              <1> 
  4263                              <1> sysstty_tmout_err:
  4264 0000377F C705[4F650000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4264 00003787 0000                <1>
  4265 00003789 E953F9FFFF          <1> 	jmp	error
  4266                              <1> 
  4267                              <1> sysstty_6:
  4268                              <1> 	;push	dx
  4269                              <1> 	;push	cx
  4270                              <1> 	; 01/02/2022
  4271 0000378E 52                  <1> 	push	edx
  4272 0000378F 51                  <1> 	push	ecx
  4273 00003790 891D[18650000]      <1> 	mov	[u.namep], ebx
  4274 00003796 E846080000          <1> 	call	namei
  4275                              <1> 	; 01/02/2022
  4276 0000379B 59                  <1> 	pop	ecx
  4277 0000379C 5A                  <1> 	pop	edx
  4278                              <1> 	;pop	cx
  4279                              <1> 	;pop	dx
  4280 0000379D 725A                <1> 	jc	short sysstty_inv_dn
  4281                              <1> 	;
  4282 0000379F 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4283 000037A3 7754                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4284                              <1> 	;
  4285 000037A5 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4286                              <1> 		       ; /dev/COM1, /dev/COM2
  4287 000037A7 7206                <1> 	jb	short sysstty_7
  4288 000037A9 2C0A                <1> 	sub	al, 10
  4289                              <1> 	; al = 0 to 9
  4290 000037AB 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  4291 000037AD EB11                <1> 	jmp	short sysstty_8
  4292                              <1> 
  4293                              <1> sysstty_7:
  4294 000037AF 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4295 000037B1 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4296 000037B3 0FB61D[49650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4297 000037BA 8A83[53620000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4298                              <1> sysstty_8:
  4299                              <1> 	; 22/02/2022
  4300                              <1> 	; (ebx < 256)
  4301 000037C0 A2[00650000]        <1> 	mov	[u.r0], al
  4302                              <1> 	; 01/02/2022
  4303                              <1> 	;push	dx
  4304                              <1> 	;push	ax
  4305                              <1> 	;push	cx
  4306 000037C5 52                  <1> 	push	edx
  4307 000037C6 50                  <1> 	push	eax
  4308 000037C7 51                  <1> 	push	ecx
  4309 000037C8 E827190000          <1> 	call	ottyp
  4310 000037CD 59                  <1> 	pop	ecx
  4311 000037CE 58                  <1> 	pop	eax
  4312 000037CF 5A                  <1> 	pop	edx
  4313                              <1> 	;pop	cx
  4314                              <1> 	;pop	ax
  4315                              <1> 	;pop	dx
  4316                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4317                              <1> 	; 01/02/2022
  4318 000037D0 7305                <1> 	jnc	short sysstty_21
  4319 000037D2 E941FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4320                              <1> sysstty_21:
  4321                              <1> 	; 29/10/2015
  4322 000037D7 86E9                <1> 	xchg 	ch, cl
  4323                              <1> 		; cl = character, ch = color code
  4324 000037D9 86C1                <1> 	xchg	al, cl
  4325                              <1> 		; al = character, cl = tty number
  4326 000037DB 80F907              <1> 	cmp	cl, 7
  4327                              <1> 	;ja	sysstty_12
  4328                              <1> 	; 01/02/2022
  4329 000037DE 7628                <1> 	jna	short sysstty_16
  4330                              <1> ;;
  4331 000037E0 80FEFF              <1> 	cmp	dh, 0FFh
  4332 000037E3 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4333                              <1> 
  4334                              <1> ; 01/02/2022
  4335                              <1> ;	; 29/10/2015
  4336                              <1> ;	mov	ah, dl ; communication parameters
  4337                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4338                              <1> ;		;			 THRE int + RDA int 
  4339                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4340                              <1> ;		;			 THRE int + RDA int 
  4341                              <1> ;	sub	al, al ; 0
  4342                              <1> ;	; 12/07/2014
  4343                              <1> ;	cmp	cl, 9
  4344                              <1> ;	jb	short sysstty_1
  4345                              <1> ;	inc	al
  4346                              <1> ;sysstty_1:
  4347                              <1> ;	; 01/02/2022
  4348                              <1> ;	push	ecx
  4349                              <1> ;	;push	cx
  4350                              <1> ;	; 29/06/2015	
  4351                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4352                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4353                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4354                              <1> ;	; 01/02/2022
  4355                              <1> ;	pop	ecx	
  4356                              <1> ;	;pop	cx
  4357                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4358                              <1> 
  4359                              <1> 	; 02/02/2022
  4360 000037E5 88C5                <1> 	mov	ch, al ; save char
  4361                              <1> 	; 01/02/2022
  4362 000037E7 E84D000000          <1> 	call	sysstty_scp
  4363 000037EC 7291                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4364                              <1> 	; 02/02/2022
  4365 000037EE 88E8                <1> 	mov	al, ch ; restore char
  4366                              <1> sysstty_22:
  4367                              <1> 	; 01/02/2022
  4368 000037F0 08ED                <1> 	or	ch, ch
  4369 000037F2 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4370                              <1> 	; send char to (serial port) terminal
  4371                              <1> 	; al = character
  4372                              <1> 	; cl = tty number (8 or 9)
  4373 000037F4 E948FFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4374                              <1> 
  4375                              <1> sysstty_inv_dn: 
  4376                              <1> 	; 27/06/2015
  4377                              <1> 	; Invalid device name (not a tty) ! error
  4378                              <1> 	; (Device is not a tty or device name not found)
  4379 000037F9 C705[4F650000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4379 00003801 0000                <1>
  4380 00003803 E9D9F8FFFF          <1> 	jmp	error 
  4381                              <1> 
  4382                              <1> sysstty_16:
  4383                              <1> 	; 22/02/2022
  4384                              <1> 	; 16/01/2014
  4385                              <1> 	;xor	bh, bh
  4386                              <1> sysstty_9: 	; tty 0 to tty 7
  4387                              <1> 	; al = character
  4388                              <1> 	; ch = color/attribute ; 01/02/2022
  4389                              <1> 	;
  4390                              <1>  	; 22/02/2022 (BugFix)
  4391                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4392 00003808 29DB                <1> 	sub	ebx, ebx ; *
  4393 0000380A 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4394                              <1> 	;
  4395 0000380C 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4396 0000380F 7409                <1> 	je	short sysstty_10
  4397                              <1> 	; 02/02/2022
  4398 00003811 51                  <1> 	push	ecx
  4399 00003812 50                  <1> 	push	eax
  4400                              <1> 	;push	cx
  4401                              <1> 	;push	ax	
  4402                              <1> 	; 22/02/2022	
  4403                              <1> 	;;movzx	ebx, cl ; *
  4404                              <1> 	;mov	bl, cl ; (tty number = video page number)
  4405 00003813 E8A7DBFFFF          <1> 	call	set_cpos
  4406                              <1> 	;pop	ax
  4407                              <1> 	;pop	cx
  4408                              <1> 	; 02/02/2022
  4409 00003818 58                  <1> 	pop	eax
  4410 00003819 59                  <1> 	pop	ecx
  4411                              <1> sysstty_10: 
  4412                              <1> 	; 29/10/2015
  4413 0000381A 08C0                <1> 	or	al, al ; character
  4414 0000381C 740D                <1> 	jz      short sysstty_11 ; al = 0
  4415                              <1> 	; 17/11/2015
  4416 0000381E 3CFF                <1> 	cmp	al, 0FFh
  4417 00003820 7309                <1> 	jnb	short sysstty_11
  4418                              <1> 		; ch > 0 and ch < FFh
  4419                              <1> 	; write a character at current cursor position
  4420 00003822 88EC                <1> 	mov	ah, ch ; color/attribute
  4421                              <1> 	; 12/07/2014
  4422                              <1> 	;push	cx
  4423                              <1> 	; 02/02/2022
  4424 00003824 51                  <1> 	push	ecx
  4425 00003825 E87DDCFFFF          <1> 	call	write_c_current
  4426                              <1> 	;pop	cx
  4427                              <1> 	; 02/02/2022
  4428 0000382A 59                  <1> 	pop	ecx
  4429                              <1> sysstty_11:
  4430                              <1> 	; 14/01/2014
  4431 0000382B 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4432                              <1> 	; 18/01/2014
  4433                              <1> 	;movzx	eax, cl ; 27/06/2015
  4434 0000382D 88C8                <1> 	mov	al, cl
  4435 0000382F E8E3190000          <1> 	call	cttyp
  4436 00003834 E9C8F8FFFF          <1> 	jmp	sysret
  4437                              <1> 
  4438                              <1> sysstty_scp:
  4439                              <1> 	; 02/02/2022
  4440                              <1> 	; set communication parameters (for COM1 or COM2)
  4441                              <1> 	; 01/02/2022
  4442                              <1> 	;
  4443                              <1> 	; 29/10/2015
  4444 00003839 88D4                <1> 	mov	ah, dl ; communication parameters
  4445                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4446                              <1> 		;			 THRE int + RDA int 
  4447                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4448                              <1> 		;			 THRE int + RDA int 
  4449 0000383B 28C0                <1> 	sub	al, al ; 0
  4450                              <1> 	; 12/07/2014
  4451 0000383D 80F909              <1> 	cmp	cl, 9
  4452 00003840 7202                <1> 	jb	short sysstty_1
  4453 00003842 FEC0                <1> 	inc	al
  4454                              <1> sysstty_1:
  4455                              <1> 	; 02/02/2022
  4456 00003844 52                  <1> 	push	edx
  4457                              <1> 	; 01/02/2022
  4458 00003845 51                  <1> 	push	ecx
  4459                              <1> 	;push	cx
  4460                              <1> 	; 29/06/2015	
  4461 00003846 E854F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4462 0000384B 66890D[01650000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4463                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4464                              <1> 	; 01/02/2022
  4465 00003852 59                  <1> 	pop	ecx	
  4466                              <1> 	;pop	cx
  4467 00003853 5A                  <1> 	pop	edx ; 02/02/2022
  4468                              <1> 	; 01/02/2022
  4469                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4470 00003854 C3                  <1> 	retn
  4471                              <1> 
  4472                              <1> sysstty_14:
  4473                              <1> 	; 23/02/2022
  4474                              <1> 	; 02/02/2022
  4475                              <1> 	; ch = 0
  4476                              <1> 	; cl = video page
  4477                              <1> 	;
  4478                              <1> 	; dx = 0FFFFh
  4479                              <1> 	; clear screen (video page)
  4480                              <1> 	;
  4481                              <1> 
  4482                              <1> 	; 02/02/2022
  4483                              <1> 	; clear screen
  4484                              <1> 	;
  4485                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4486                              <1> 
  4487                              <1> 	; 23/02/2022
  4488 00003855 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4489                              <1> 
  4490                              <1> 	; clear video page
  4491 00003857 E810000000          <1> 	call	wttyc ; 23/02/2022
  4492                              <1> 
  4493                              <1> 	; 23/02/2022
  4494 0000385C 88D8                <1> 	mov	al, bl
  4495 0000385E 8A25[49650000]      <1> 	mov	ah, [u.uno]
  4496 00003864 66A3[00650000]      <1> 	mov	[u.r0], ax
  4497 0000386A EBBF                <1> 	jmp	short sysstty_11
  4498                              <1> 
  4499                              <1> vp_clr:	; 27/02/2022
  4500                              <1> wttyc:
  4501                              <1> 	; 23/02/2022
  4502                              <1> 	; (clear video page)
  4503                              <1> 	; INPUT:
  4504                              <1> 	;  bl = video page (0 to 7)
  4505                              <1> 	;
  4506                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4507                              <1> 
  4508                              <1> 	;xor	dx, dx ; column 0, row 0
  4509                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4510                              <1> 	;
  4511                              <1> ;	movzx	ebx, cl
  4512                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4513                              <1> 
  4514                              <1> ;	shl 	bl, 1 
  4515                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4516                              <1> ;		; AL = lock value (0 or process number)
  4517                              <1> ;	or	al, al
  4518                              <1> ;	jz	short @f
  4519                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4520                              <1> ;	jne	short sysstty_15
  4521                              <1> ;		; only the owner can clear its video page
  4522                              <1> ;	xor	al, al ; 0
  4523                              <1> ;@@:
  4524                              <1> ;	;mov	bl, cl		
  4525                              <1> ;	shr	bl, 1 
  4526                              <1> 
  4527 0000386C 30C0                <1> 	xor	al, al	; 0
  4528 0000386E B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4529                              <1> 
  4530                              <1> 	; scroll_up input:
  4531                              <1> 	;
  4532                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4533                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4534                              <1> 	; ah = attribute to be used on blanked line
  4535                              <1> 	; bl = video page number (0 to 7)
  4536                              <1> 
  4537 00003870 E8D0DBFFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4538                              <1> 
  4539                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4540                              <1> 
  4541                              <1> 	; bl = video page number (0 to 7)
  4542                              <1> 	;xor	dx, dx ; column 0, row 0
  4543                              <1> 	; 02/02/2022
  4544 00003875 31D2                <1> 	xor	edx, edx
  4545                              <1> 	; 23/02/2022
  4546                              <1> 	;call	set_cpos
  4547                              <1> 	;retn
  4548 00003877 E943DBFFFF          <1> 	jmp	set_cpos
  4549                              <1> 
  4550                              <1> 	;mov	al, bl
  4551                              <1> 	;mov	ah, [u.uno]
  4552                              <1> 	;mov	[u.r0], ax
  4553                              <1> 	;jmp	short sysstty_11
  4554                              <1> 
  4555                              <1> ;sysstty_15:
  4556                              <1> ;	; 30/01/2022
  4557                              <1> ;	; permission (denied) error
  4558                              <1> ;	;xor	dl, dl ; sysstty call sign
  4559                              <1> ;	mov	al, cl
  4560                              <1> ;	sub	ah, ah ; 0
  4561                              <1> ;	call	cttyp
  4562                              <1> ;	jmp	error
  4563                              <1> 
  4564                              <1> ; Original UNIX v1 'sysstty' routine:
  4565                              <1> ; gtty:
  4566                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4567                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4568                              <1> 	; 		/ r2 has source
  4569                              <1>         ;mov    r2,-(sp)
  4570                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4571                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4572                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4573                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4574                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4575                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4576                              <1>         ;       br .+4 / list empty, skip branch
  4577                              <1>         ;br     1b / get another character until list is empty
  4578                              <1>         ;mov    0b,r1 / move cc offset to r1
  4579                              <1>         ;inc    r1 / bump it for output clist
  4580                              <1>         ;tstb   cc(r1) / is it 0
  4581                              <1>         ;beq    1f / yes, no characters to output
  4582                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4583                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4584                              <1>         ;br     1b / try to calm it down again
  4585                              <1> ;1:
  4586                              <1>         ;mov    (sp)+,r1
  4587                              <1>         ;mov    (sp)+,r2 / restore registers
  4588                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4589                              <1>         ;beq    1f / if 0, 1f
  4590                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4591                              <1>         ;                   / control status register
  4592                              <1> ;1:
  4593                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4594                              <1>         ;beq    1f / if 0 1f
  4595                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4596                              <1> 	;		    / control status reg
  4597                              <1> ;1:
  4598                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4599                              <1>         ;jmp	sysret2 / return to user
  4600                              <1> 
  4601                              <1> sysgtty: ; < get tty status >
  4602                              <1> 	; 22/02/2022
  4603                              <1> 	; 01/02/2022
  4604                              <1> 	; 23/11/2015
  4605                              <1> 	; 29/10/2015
  4606                              <1> 	; 17/10/2015
  4607                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4608                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4609                              <1> 	;
  4610                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4611                              <1> 	; It stores in the three words addressed by it's argument
  4612                              <1> 	; the status of the typewriter whose file descriptor
  4613                              <1> 	; in (u.r0).
  4614                              <1> 	;
  4615                              <1> 	; Calling sequence:
  4616                              <1> 	;	sysgtty; arg
  4617                              <1> 	; Arguments:
  4618                              <1> 	;	arg - address of 3 words destination of the status
  4619                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4620                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4621                              <1> 	; ...............................................................
  4622                              <1> 	;	
  4623                              <1> 	; Retro UNIX 8086 v1 modification: 
  4624                              <1> 	;	'sysgtty' system call will return status of tty
  4625                              <1> 	;	(keyboard, serial port and video page status)
  4626                              <1> 	;	 in following manner:
  4627                              <1> 	;
  4628                              <1> 	; Inputs:
  4629                              <1> 	;	BX = 0 --> means 
  4630                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4631                              <1> 	;	                 for (current) process
  4632                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4633                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4634                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4635                              <1> 	;	     CH > 0 -->	tty number + 1
  4636                              <1> 	;
  4637                              <1> 	;	BX > 0 --> points to name of tty
  4638                              <1> 	;	     CL = 0 --> return keyboard status
  4639                              <1> 	;	     CL = 1 --> return video page status
  4640                              <1> 	;	     CH = undefined		 
  4641                              <1> 	;
  4642                              <1> 	; Outputs:
  4643                              <1> 	;	cf = 0 ->
  4644                              <1> 	;
  4645                              <1> 	;	     AL = tty number from 0 to 9
  4646                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4647                              <1> 	;	     AH = 0 if the tty is free/unused
  4648                              <1> 	;	     AH = the process number of the caller 
  4649                              <1>  	;	     AH = FFh if the tty is locked by another process
  4650                              <1> 	;
  4651                              <1> 	;	  (if calling is for serial port status)
  4652                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4653                              <1> 	;		  (BH = modem status, BL = Line status)
  4654                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4655                              <1> 	;	     CX = 0 (if data is not ready or undefined)
  4656                              <1> 	;
  4657                              <1> 	;	  (if calling is for keyboard status)
  4658                              <1> 	;	     BX = current character in tty/keyboard buffer
  4659                              <1> 	;		  (BH = scan code, BL = ascii code)
  4660                              <1> 	;		  (BX=0 if there is not a waiting character)
  4661                              <1> 	;	     CX  is undefined
  4662                              <1> 	;
  4663                              <1> 	;	  (if calling is for video page status)	
  4664                              <1> 	;	     BX = cursor position on the video page
  4665                              <1> 	;		  if tty number < 8
  4666                              <1> 	;		  (BH = row, BL = column)
  4667                              <1> 	;	     CX = current character (in cursor position)
  4668                              <1> 	;		  on the video page of the tty 
  4669                              <1> 	;		  if tty number < 8
  4670                              <1> 	;		  (CH = color, CL = character)
  4671                              <1> 	;	
  4672                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4673                              <1> 	;
  4674                              <1> 	;	     AH = FFh if the caller is not owner of
  4675                              <1> 	;		  specified tty or console tty
  4676                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4677                              <1> 	;	     BX, CX are undefined if cf = 1
  4678                              <1> 	;
  4679                              <1> 	;	  (If tty number is 8 or 9)
  4680                              <1> 	;	     AL = tty number 
  4681                              <1> 	;	     AH = the process number of the caller 
  4682                              <1> 	;	     BX = serial port status
  4683                              <1> 	;  		 (BH = modem status, BL = Line status)
  4684                              <1> 	;	     CX = 0
  4685                              <1> 	;
  4686                              <1> 		
  4687                              <1> gtty:   ; get (requested) tty number
  4688                              <1> 	; 22/02/2022
  4689                              <1> 	; 01/02/2022
  4690                              <1> 	; 17/10/2015
  4691                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4692                              <1> 	; 30/05/2013 - 12/07/2014
  4693                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4694                              <1> 	;
  4695                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4696                              <1> 	;
  4697                              <1> 	; 28/06/2015 (32 bit modifications)
  4698                              <1> 	; 16/01/2014
  4699 0000387C 31C0                <1> 	xor 	eax, eax
  4700 0000387E 6648                <1> 	dec	ax ; 17/10/2015
  4701 00003880 A3[00650000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4702 00003885 80F901              <1> 	cmp	cl, 1
  4703 00003888 760F                <1> 	jna	short sysgtty_0
  4704                              <1> sysgtty_invp:
  4705                              <1> 	; 28/06/2015
  4706 0000388A C705[4F650000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4706 00003892 0000                <1>
  4707 00003894 E948F8FFFF          <1> 	jmp	error
  4708                              <1> sysgtty_0:	
  4709 00003899 21DB                <1> 	and	ebx, ebx
  4710 0000389B 742E                <1> 	jz	short sysgtty_1
  4711                              <1> 	;
  4712 0000389D 891D[18650000]      <1> 	mov	[u.namep], ebx
  4713                              <1> 	;push	cx ; 23/11/2015
  4714                              <1> 	; 01/02/2022
  4715 000038A3 51                  <1> 	push	ecx
  4716 000038A4 E838070000          <1> 	call	namei
  4717                              <1> 	; 01/02/2022
  4718 000038A9 59                  <1> 	pop	ecx
  4719                              <1> 	;pop	cx ; 23/11/2015
  4720 000038AA 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4721                              <1> 	;
  4722 000038AC 6683F801            <1> 	cmp	ax, 1
  4723 000038B0 7622                <1> 	jna	short sysgtty_2
  4724                              <1> 	; 01/02/2022
  4725 000038B2 20E4                <1> 	and	ah, ah
  4726 000038B4 7506                <1> 	jnz	short sysgtty_inv_dn
  4727                              <1> 	;sub	ax, 10
  4728 000038B6 2C0A                <1> 	sub	al, 10
  4729 000038B8 3C09                <1> 	cmp	al, 9
  4730                              <1> 	;cmp	ax, 9
  4731                              <1> 	;ja	short sysgtty_inv_dn
  4732                              <1> 	;mov	ch, al
  4733                              <1> 	;jmp	short sysgtty_4
  4734                              <1> 	; 23/11/2015
  4735 000038BA 7629                <1> 	jna	short sysgtty_4
  4736                              <1> sysgtty_inv_dn: 
  4737                              <1> 	; 28/06/2015
  4738                              <1> 	; Invalid device name (not a tty) ! error
  4739                              <1> 	; (Device is not a tty or device name not found)
  4740 000038BC C705[4F650000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4740 000038C4 0000                <1>
  4741 000038C6 E916F8FFFF          <1> 	jmp	error 
  4742                              <1> sysgtty_1:
  4743                              <1> 	; 16/01/2014
  4744 000038CB 80FD0A              <1> 	cmp	ch, 10
  4745 000038CE 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4746 000038D0 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4747 000038D2 790F                <1> 	jns	short sysgtty_3 ; not negative
  4748                              <1> 	;
  4749                              <1> sysgtty_2:
  4750                              <1> 	; get tty number of console tty
  4751 000038D4 8A25[49650000]      <1> 	mov	ah, [u.uno]
  4752                              <1>  	; 28/06/2015
  4753 000038DA 0FB6DC              <1> 	movzx 	ebx, ah
  4754 000038DD 8AAB[53620000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4755                              <1> sysgtty_3:
  4756 000038E3 88E8                <1> 	mov	al, ch
  4757                              <1> sysgtty_4:
  4758 000038E5 A2[00650000]        <1> 	mov	[u.r0], al
  4759                              <1>  	; 28/06/2015
  4760                              <1> 	;cmp	al, 9
  4761                              <1> 	;ja	short sysgtty_invp
  4762 000038EA 8B2D[FC640000]      <1> 	mov	ebp, [u.usp]
  4763                              <1> 	; 23/11/2015
  4764 000038F0 20C9                <1> 	and	cl, cl
  4765 000038F2 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4766 000038F4 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4767 000038F6 722E                <1> 	jb	short sysgtty_6 ; video page status
  4768                              <1> 	; serial port status
  4769                              <1> 	; 12/07/2014
  4770                              <1> 	;mov	dx, 0
  4771                              <1> 	;je	short sysgtty_5
  4772                              <1> 	;inc	dl
  4773                              <1> ;sysgtty_5:
  4774                              <1> 	; 28/06/2015
  4775 000038F8 2C08                <1> 	sub	al, 8
  4776 000038FA E898F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4777                              <1> 	; AL = Line status, AH = Modem status
  4778 000038FF 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4779 00003903 8A25[49650000]      <1> 	mov	ah, [u.uno]
  4780 00003909 8825[01650000]      <1>         mov     [u.r0+1], ah
  4781 0000390F 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)	
  4782                              <1> 				; (in ECX)
  4783 00003915 A880                <1> 	test	al, 80h
  4784 00003917 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4785 00003919 A801                <1> 	test	al, 1
  4786                              <1> 	;jz	sysret
  4787 0000391B 7404                <1> 	jz	short sysgtty_10 ; 22/02/2022
  4788 0000391D 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)	
  4789                              <1> sysgtty_10:
  4790 00003921 E9DBF7FFFF          <1> 	jmp	sysret
  4791                              <1> sysgtty_6:
  4792 00003926 A2[4E650000]        <1> 	mov	[u.ttyn], al ; tty number
  4793                              <1> 	;movzx	ebx, al
  4794 0000392B 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4795 0000392D D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4796                              <1> 	; 22/04/2014 - 29/06/2015
  4797 0000392F 81C3[84610000]      <1>         add     ebx, ttyl
  4798 00003935 8A23                <1>  	mov	ah, [ebx]
  4799 00003937 3A25[49650000]      <1> 	cmp	ah, [u.uno]
  4800 0000393D 7404                <1> 	je	short sysgtty_7
  4801 0000393F 20E4                <1> 	and	ah, ah
  4802                              <1> 	;jz	short sysgtty_7
  4803 00003941 7506                <1> 	jnz	short sysgtty_8
  4804                              <1> 	;mov	ah, 0FFh
  4805                              <1> sysgtty_7:
  4806 00003943 8825[01650000]      <1>         mov     [u.r0+1], ah
  4807                              <1> sysgtty_8:
  4808 00003949 08C9                <1> 	or	cl, cl
  4809 0000394B 7510                <1> 	jnz	short sysgtty_9
  4810 0000394D B001                <1> 	mov	al, 1  ; test a key is available
  4811 0000394F E8391C0000          <1> 	call	getc
  4812 00003954 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4813 00003958 E9A4F7FFFF          <1> 	jmp	sysret
  4814                              <1> sysgtty_9:
  4815 0000395D 8A1D[4E650000]      <1> 	mov	bl, [u.ttyn]
  4816                              <1> 	; bl = video page number
  4817 00003963 E8961D0000          <1> 	call 	get_cpos
  4818                              <1> 	; dx = cursor position
  4819 00003968 66895510            <1> 	mov	[ebp+16], dx ; bx
  4820                              <1> 	;mov	bl, [u.ttyn]
  4821                              <1> 	; bl = video page number
  4822 0000396C E89E1D0000          <1> 	call	read_ac_current
  4823                              <1> 	; ax = character and attribute/color
  4824 00003971 66894518            <1> 	mov	[ebp+24], ax ; cx
  4825 00003975 E987F7FFFF          <1> 	jmp	sysret
  4826                              <1> sysgtty_dnr_err:
  4827                              <1> 	; 'device not responding !' error	
  4828                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4829 0000397A C705[4F650000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ;  25
  4829 00003982 0000                <1>
  4830 00003984 E958F7FFFF          <1> 	jmp	error	
  4831                              <1> 
  4832                              <1> ; Original UNIX v1 'sysgtty' routine:
  4833                              <1> ; sysgtty:
  4834                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4835                              <1> 	;	       / r2 has destination
  4836                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4837                              <1> 	;                     / in 1st word of dest
  4838                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4839                              <1> 	;                     / in 2nd word of dest
  4840                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4841                              <1>         ;jmp    sysret2 / return to user
  4842                              <1> 	
  4843                              <1> ; Original UNIX v1 'gtty' routine:
  4844                              <1> ; gtty:
  4845                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4846                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4847                              <1>         ;jsr    r0,getf / get the i-number of the file
  4848                              <1>         ;tst    r1 / is it open for reading
  4849                              <1>         ;bgt    1f / yes
  4850                              <1>         ;neg    r1 / no, i-number is negative, 
  4851                              <1> 	;          / so make it positive
  4852                              <1> ;1:
  4853                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4854                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4855                              <1>         ;bhis   error9 / no, error
  4856                              <1>         ;asl    r1 / 0%2
  4857                              <1>         ;asl    r1 / 0%4 / yes
  4858                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4859                              <1> 	;	       ; / tty block
  4860                              <1>         ;mov    u.off,r2 / put argument in r2
  4861                              <1>         ;rts    r0 / return
  2053                                  %include 'u2.s'        ; 11/05/2015
  2054                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS2.INC
  2055                              <1> ; Last Modification: 15/05/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 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2066                              <1> ;
  2067                              <1> ; ****************************************************************************
  2068                              <1> ; 03/01/2016
  2069                              <1> 
  2070                              <1> syslink:
  2071                              <1> 	; 03/02/2022
  2072                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2073                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2074                              <1> 	;
  2075                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2076                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2077                              <1> 	; given to the entry that will go in the current directory.
  2078                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2079                              <1> 	; in the name 2 entry of current directory is the same
  2080                              <1> 	; i-number for the name 1 file.
  2081                              <1> 	;
  2082                              <1> 	; Calling sequence:
  2083                              <1> 	;	syslink; name 1; name 2
  2084                              <1> 	; Arguments:
  2085                              <1> 	;	name 1 - file name to which link will be created.
  2086                              <1> 	;	name 2 - name of entry in current directory that
  2087                              <1> 	;		 links to name 1.
  2088                              <1> 	; Inputs: -
  2089                              <1> 	; Outputs: -
  2090                              <1> 	; ...............................................................
  2091                              <1> 	;	
  2092                              <1> 	; Retro UNIX 8086 v1 modification: 
  2093                              <1> 	;       'syslink' system call has two arguments; so,
  2094                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2095                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2096                              <1> 	;
  2097                              <1> 		; / name1, name2
  2098                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2099 00003989 891D[18650000]      <1> 	mov	[u.namep], ebx
  2100 0000398F 51                  <1> 	push	ecx
  2101 00003990 E84C060000          <1> 	call	namei
  2102                              <1> 		; jsr r0,namei / find the i-number associated with
  2103                              <1> 			     ; / the 1st path name
  2104                              <1>      	;;and	ax, ax
  2105                              <1> 	;;jz	error ; File not found
  2106                              <1> 	;jc	error 
  2107                              <1> 		; br error9 / cannot be found
  2108 00003995 730F                <1> 	jnc	short syslink0
  2109                              <1> 	;pop 	ecx
  2110                              <1> 	; 'file not found !' error
  2111 00003997 C705[4F650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2111 0000399F 0000                <1>
  2112 000039A1 E93BF7FFFF          <1> 	jmp	error
  2113                              <1> syslink0:
  2114 000039A6 E84B0E0000          <1> 	call	iget
  2115                              <1> 		; jsr r0,iget / get the i-node into core
  2116 000039AB 8F05[18650000]      <1> 	pop	dword [u.namep] ; ecx
  2117                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2118                              <1> 	; 03/02/2022
  2119 000039B1 50                  <1> 	push	eax
  2120                              <1> 	;push	ax
  2121                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2122                              <1> 			    ; / (a link to this file is to be created)
  2123 000039B2 66FF35[E4640000]    <1> 	push	word [cdev]
  2124                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2125 000039B9 E852000000          <1> 	call	isdir
  2126                              <1> 		; jsr r0,isdir / is it a directory
  2127 000039BE E81E060000          <1> 	call	namei
  2128                              <1> 		; jsr r0,namei / no, get i-number of name2
  2129                              <1> 	;jnc	error
  2130                              <1> 		; br .+4   / not found 
  2131                              <1> 			 ; / so r1 = i-number of current directory
  2132                              <1> 			 ; / ii = i-number of current directory
  2133                              <1> 		; br error9 / file already exists., error
  2134 000039C3 720F                <1> 	jc	short syslink1
  2135                              <1> 	; pop ax
  2136                              <1> 	; pop ax
  2137                              <1> 	; 'file exists !' error
  2138 000039C5 C705[4F650000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2138 000039CD 0000                <1>
  2139 000039CF E90DF7FFFF          <1> 	jmp	error
  2140                              <1> syslink1:
  2141 000039D4 6659                <1> 	pop	cx
  2142                              <1> 	;cmp	cx, [cdev]
  2143 000039D6 3A0D[E4640000]      <1> 	cmp	cl, [cdev]
  2144                              <1> 	;jne	error
  2145                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2146                              <1> 			       ; / end of current directory
  2147                              <1> 	        ; bne error9
  2148 000039DC 740F                <1> 	je	short syslink2
  2149                              <1> 	; 'not same drive !' error
  2150 000039DE C705[4F650000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2150 000039E6 0000                <1>
  2151 000039E8 E9F4F6FFFF          <1> 	jmp	error
  2152                              <1> syslink2:
  2153                              <1> 	;pop	ax
  2154                              <1> 	;push	ax
  2155                              <1> 	; 03/02/2022
  2156                              <1> 	;mov	eax, [esp]
  2157 000039ED 58                  <1> 	pop	eax
  2158 000039EE 50                  <1> 	push	eax
  2159 000039EF 66A3[32650000]      <1> 	mov	[u.dirbuf], ax
  2160                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2161 000039F5 E89E000000          <1> 	call	mkdir
  2162                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2163                              <1> 		 	     ; / in current directory
  2164                              <1> 	; 03/02/2022
  2165 000039FA 58                  <1> 	pop	eax
  2166                              <1> 	;pop	ax
  2167                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2168 000039FB E8F60D0000          <1> 	call	iget
  2169                              <1> 		; jsr r0,iget / get i-node into core
  2170 00003A00 FE05[F6610000]      <1> 	inc	byte [i.nlks]
  2171                              <1> 		; incb i.nlks / add 1 to its number of links
  2172 00003A06 E8F50E0000          <1> 	call	setimod
  2173                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2174 00003A0B E9F1F6FFFF          <1> 	jmp	sysret
  2175                              <1> 
  2176                              <1> isdir:
  2177                              <1> 	; 03/02/2022
  2178                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2179                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2180                              <1> 	;
  2181                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2182                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2183                              <1> 	;  called by syslink and sysunlink to make sure directories
  2184                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2185                              <1> 	; 'isdir' does not bother checking. The current i-node
  2186                              <1> 	;  is not disturbed.			
  2187                              <1> 	;		
  2188                              <1> 	; INPUTS ->
  2189                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2190                              <1> 	;    u.uid - user id
  2191                              <1> 	; OUTPUTS ->
  2192                              <1> 	;    r1 - contains current i-number upon exit
  2193                              <1> 	;    	 (current i-node back in core) 
  2194                              <1> 	;	
  2195                              <1> 	; ((AX = R1))
  2196                              <1> 	;
  2197                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2198                              <1> 	;
  2199                              <1> 
  2200                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2201                              <1> 	; / there is an error unless super user made the call
  2202                              <1> 	
  2203 00003A10 803D[46650000]00    <1> 	cmp	byte [u.uid], 0 
  2204                              <1> 		; tstb u.uid / super user
  2205 00003A17 762B                <1> 	jna	short isdir1
  2206                              <1> 		; beq 1f / yes, don't care
  2207 00003A19 66FF35[E0640000]    <1> 	push	word [ii]
  2208                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2209 00003A20 E8D10D0000          <1> 	call	iget
  2210                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2211                              <1> 	; 03/02/2022
  2212 00003A25 F605[F5610000]40    <1> 	test	byte [i.flgs+1], 40h
  2213                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2214                              <1> 		; bit $40000,i.flgs / is it a directory
  2215                              <1> 	;jnz	error
  2216                              <1> 		; bne error9 / yes, error
  2217 00003A2C 740F                <1> 	jz	short isdir0
  2218 00003A2E C705[4F650000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2218 00003A36 0000                <1>
  2219                              <1> 				; 'permission denied !' error
  2220                              <1> 	;pop	ax
  2221 00003A38 E9A4F6FFFF          <1> 	jmp	error	
  2222                              <1> isdir0:	
  2223 00003A3D 6658                <1> 	pop	ax
  2224                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2225 00003A3F E8B20D0000          <1> 	call	iget
  2226                              <1> 		; jsr r0,iget / get it back in
  2227                              <1> isdir1: ; 1:
  2228 00003A44 C3                  <1> 	retn
  2229                              <1> 		; rts r0
  2230                              <1> 
  2231                              <1> sysunlink:
  2232                              <1> 	; 03/02/2022
  2233                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2234                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2235                              <1> 	;
  2236                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2237                              <1> 	; name from its directory. If this entry was the last link
  2238                              <1> 	; to the file, the contents of the file are freed and the
  2239                              <1> 	; file is destroyed. If, however, the file was open in any
  2240                              <1> 	; process, the actual destruction is delayed until it is 
  2241                              <1> 	; closed, even though the directory entry has disappeared.
  2242                              <1> 	; 
  2243                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2244                              <1> 	; does not exist or that its directory can not be written.
  2245                              <1> 	; Write permission is not required on the file itself.
  2246                              <1> 	; It is also illegal to unlink a directory (except for
  2247                              <1> 	; the superuser).
  2248                              <1> 	;
  2249                              <1> 	; Calling sequence:
  2250                              <1> 	;	sysunlink; name
  2251                              <1> 	; Arguments:
  2252                              <1> 	;	name - name of directory entry to be removed 
  2253                              <1> 	; Inputs: -
  2254                              <1> 	; Outputs: -
  2255                              <1> 	; ...............................................................
  2256                              <1> 	;				
  2257                              <1> 	; Retro UNIX 8086 v1 modification:
  2258                              <1> 	;	 The user/application program puts address of the name
  2259                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2260                              <1> 
  2261                              <1> 	; / name - remove link name
  2262 00003A45 891D[18650000]      <1> 	mov	[u.namep], ebx
  2263                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2264 00003A4B E891050000          <1> 	call	namei
  2265                              <1> 		; jsr r0,namei / find the i-number associated 
  2266                              <1> 			     ; / with the path name
  2267                              <1> 	;jc	error
  2268                              <1> 		; br error9 / not found
  2269 00003A50 730F                <1> 	jnc	short sysunlink1
  2270                              <1> 	; 'file not found !' error
  2271 00003A52 C705[4F650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2271 00003A5A 0000                <1>
  2272 00003A5C E980F6FFFF          <1> 	jmp	error
  2273                              <1> sysunlink1:
  2274                              <1> 	; 03/02/2022
  2275 00003A61 50                  <1> 	push	eax
  2276                              <1> 	;push	ax
  2277                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2278 00003A62 E8A9FFFFFF          <1> 	call	isdir
  2279                              <1> 		; jsr r0,isdir / is it a directory
  2280                              <1> 	;xor 	ax, ax
  2281                              <1> 	; 03/02/2022
  2282 00003A67 31C0                <1> 	xor	eax, eax
  2283 00003A69 66A3[32650000]      <1> 	mov	[u.dirbuf], ax ; 0
  2284                              <1> 		; clr u.dirbuf / no, clear the location that will
  2285                              <1> 			   ; / get written into the i-number portion
  2286                              <1> 			 ; / of the entry
  2287 00003A6F 832D[1C650000]0A    <1> 	sub	dword [u.off], 10
  2288                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2289 00003A76 E865000000          <1> 	call	wdir
  2290                              <1> 		; jsr r0,wdir / free the directory entry
  2291                              <1> 	; 03/02/2022
  2292 00003A7B 58                  <1> 	pop	eax
  2293                              <1> 	;pop	ax
  2294                              <1> 		; mov (sp)+,r1 / get i-number back
  2295 00003A7C E8750D0000          <1> 	call	iget
  2296                              <1> 		; jsr r0,iget / get i-node
  2297 00003A81 E87A0E0000          <1> 	call	setimod
  2298                              <1> 		; jsr r0,setimod / set modified flag
  2299 00003A86 FE0D[F6610000]      <1> 	dec	byte [i.nlks]
  2300                              <1> 		; decb i.nlks / decrement the number of links
  2301                              <1> 	;jnz	sysret
  2302                              <1> 		; bgt sysret9 / if this was not the last link
  2303                              <1> 			    ; / to file return
  2304                              <1> 	; 03/02/2022
  2305 00003A8C 7505                <1> 	jnz	short sysunlink2
  2306                              <1> 	; AX = r1 = i-number
  2307 00003A8E E8B8090000          <1> 	call	anyi
  2308                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2309                              <1> 			 ; / Then free contents of file and destroy it.
  2310                              <1> sysunlink2:
  2311 00003A93 E969F6FFFF          <1> 	jmp	sysret
  2312                              <1> 		; br sysret9
  2313                              <1> 
  2314                              <1> mkdir:
  2315                              <1> 	; 03/02/2022
  2316                              <1> 	; 12/10/2015
  2317                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2318                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2319                              <1> 	;
  2320                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2321                              <1> 	; by u.namep into the current directory.
  2322                              <1> 	;
  2323                              <1> 	; INPUTS ->
  2324                              <1> 	;    u.namep - points to a file name 
  2325                              <1> 	;	           that is about to be a directory entry.
  2326                              <1> 	;    ii - current directory's i-number.	
  2327                              <1> 	; OUTPUTS ->
  2328                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2329                              <1> 	;    u.off - points to entry to be filled 
  2330                              <1> 	;	     in the current directory		
  2331                              <1> 	;    u.base - points to start of u.dirbuf.
  2332                              <1> 	;    r1 - contains i-number of current directory 
  2333                              <1> 	;	
  2334                              <1> 	; ((AX = R1)) output
  2335                              <1> 	;
  2336                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2337                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2338                              <1> 	;
  2339                              <1> 
  2340                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2341 00003A98 31C0                <1> 	xor 	eax, eax
  2342 00003A9A BF[34650000]        <1>         mov     edi, u.dirbuf+2
  2343 00003A9F 89FE                <1> 	mov	esi, edi
  2344 00003AA1 AB                  <1> 	stosd
  2345 00003AA2 AB                  <1> 	stosd
  2346                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2347 00003AA3 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2348                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2349                              <1> 	;mov 	ebp, [u.namep]
  2350 00003AA5 E8B9060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2351                              <1> 		; esi = physical address (page start + offset)
  2352                              <1> 		; ecx = byte count in the page (1 - 4096)
  2353                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2354                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2355                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2356                              <1> mkdir_1: ; 1: 
  2357 00003AAA 45                  <1> 	inc	ebp ; 12/10/2015
  2358                              <1> 	;
  2359                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2360                              <1> 	 ; 01/08/2013
  2361 00003AAB AC                  <1> 	lodsb
  2362                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2363 00003AAC 20C0                <1> 	and 	al, al
  2364 00003AAE 7426                <1> 	jz 	short mkdir_3 	  
  2365                              <1> 		; beq 1f / if null, done
  2366 00003AB0 3C2F                <1> 	cmp	al, '/'
  2367                              <1> 		; cmp r1,$'/ / is it a "/"?
  2368 00003AB2 7413                <1> 	je	short mkdir_err
  2369                              <1> 	;je	error
  2370                              <1> 		; beq error9 / yes, error
  2371                              <1> 	; 03/02/2022
  2372 00003AB4 49                  <1> 	dec	ecx
  2373                              <1> 	; 12/10/2015
  2374                              <1> 	;dec	cx
  2375 00003AB5 7505                <1> 	jnz	short mkdir_2
  2376                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2377 00003AB7 E8AD060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2378                              <1> 		; esi = physical address (page start + offset)
  2379                              <1> 		; ecx = byte count in the page
  2380                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2381                              <1> mkdir_2:
  2382 00003ABC 81FF[3C650000]      <1> 	cmp     edi, u.dirbuf+10
  2383                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2384                              <1> 				     ; / a char?
  2385 00003AC2 74E6                <1> 	je	short mkdir_1
  2386                              <1> 		; beq 1b / yes, go back
  2387 00003AC4 AA                  <1> 	stosb
  2388                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2389 00003AC5 EBE3                <1> 	jmp 	short mkdir_1
  2390                              <1> 		; br 1b / get next char
  2391                              <1> mkdir_err:
  2392                              <1> 	; 17/06/2015
  2393 00003AC7 C705[4F650000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2393 00003ACF 0000                <1>
  2394 00003AD1 E90BF6FFFF          <1> 	jmp	error
  2395                              <1> mkdir_3: ; 1:
  2396 00003AD6 A1[14650000]        <1> 	mov	eax, [u.dirp]
  2397 00003ADB A3[1C650000]        <1> 	mov	[u.off], eax
  2398                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2399                              <1> 				 ; / slot to u.off
  2400                              <1> wdir: 	; 03/02/2022
  2401                              <1> 	; 29/04/2013
  2402 00003AE0 C705[20650000]-     <1>         mov     dword [u.base], u.dirbuf
  2402 00003AE6 [32650000]          <1>
  2403                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2404 00003AEA C705[24650000]0A00- <1>         mov     dword [u.count], 10
  2404 00003AF2 0000                <1>
  2405                              <1> 		; mov $10.,u.count / u.count = 10
  2406 00003AF4 66A1[E0640000]      <1> 	mov	ax, [ii] 
  2407                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2408 00003AFA B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2409 00003AFC E8C90D0000          <1> 	call 	access
  2410                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2411                              <1> 				 ; / for writing
  2412                              <1> 	; AX = i-number of current directory
  2413                              <1> 	; 01/08/2013
  2414 00003B01 FE05[61650000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2415                              <1> 	;call	writei
  2416                              <1> 	;	; jsr r0,writei / write into directory
  2417                              <1> 	;retn	
  2418                              <1> 	;	; rts r0
  2419                              <1> 	; 03/02/2022
  2420 00003B07 E9B0100000          <1> 	jmp	writei
  2421                              <1> 
  2422                              <1> sysexec:
  2423                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2424                              <1> 	; 03/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18)
  2425                              <1> 	; 23/10/2015
  2426                              <1> 	; 19/10/2015
  2427                              <1> 	; 10/10/2015, 18/10/2015
  2428                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2429                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2430                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2431                              <1> 	; 24/06/2015, 25/06/2015
  2432                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2433                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2434                              <1> 	;
  2435                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2436                              <1> 	; pointed to by 'name' in the sysexec call. 
  2437                              <1> 	; 'sysexec' performs the following operations:
  2438                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2439                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2440                              <1> 	;    3. sets trap vectors to system routines.
  2441                              <1> 	;    4. loads arguments to be passed to executing file into
  2442                              <1> 	;	highest locations of user's core
  2443                              <1> 	;    5. puts pointers to arguments in locations immediately
  2444                              <1> 	;	following arguments.
  2445                              <1> 	;    6.	saves number of arguments in next location.
  2446                              <1> 	;    7. intializes user's stack area so that all registers
  2447                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2448                              <1> 	;	to core when 'sysret' restores registers 
  2449                              <1> 	;	and does an rti.
  2450                              <1> 	;    8. inializes u.r0 and u.sp
  2451                              <1> 	;    9. zeros user's core down to u.r0
  2452                              <1> 	;   10.	reads executable file from storage device into core
  2453                              <1> 	;	starting at location 'core'.
  2454                              <1> 	;   11.	sets u.break to point to end of user's code with
  2455                              <1> 	;	data area appended.
  2456                              <1> 	;   12.	calls 'sysret' which returns control at location
  2457                              <1> 	;	'core' via 'rti' instruction. 		  		
  2458                              <1> 	;
  2459                              <1> 	; Calling sequence:
  2460                              <1> 	;	sysexec; namep; argp
  2461                              <1> 	; Arguments:
  2462                              <1> 	;	namep - points to pathname of file to be executed
  2463                              <1> 	;	argp  - address of table of argument pointers
  2464                              <1> 	;	argp1... argpn - table of argument pointers
  2465                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2466                              <1> 	; Inputs: (arguments)
  2467                              <1> 	; Outputs: -	
  2468                              <1> 	; ...............................................................
  2469                              <1> 	;
  2470                              <1> 	; Retro UNIX 386 v1 modification: 
  2471                              <1> 	;	User application runs in it's own virtual space 
  2472                              <1> 	;	which is izolated from kernel memory (and other
  2473                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2474                              <1> 	;	privilige mode. Virtual start address is always 0.
  2475                              <1> 	;	User's core memory starts at linear address 400000h
  2476                              <1> 	;	(the end of the 1st 4MB).
  2477                              <1> 	;
  2478                              <1> 	; Retro UNIX 8086 v1 modification: 
  2479                              <1> 	;	user/application segment and system/kernel segment
  2480                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2481                              <1> 	;	are different (user's registers are saved to 
  2482                              <1> 	;	and then restored from system's stack.)
  2483                              <1> 	;
  2484                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2485                              <1> 	;	      arguments which were in these registers;
  2486                              <1> 	;	      but, it returns by putting the 1st argument
  2487                              <1> 	;	      in 'u.namep' and the 2nd argument
  2488                              <1> 	;	      on top of stack. (1st argument is offset of the
  2489                              <1> 	;	      file/path name in the user's program segment.)		 	
  2490                              <1> 	
  2491                              <1> 	;call	arg2
  2492                              <1> 	; * name - 'u.namep' points to address of file/path name
  2493                              <1> 	;          in the user's program segment ('u.segmnt')
  2494                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2495                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2496                              <1> 	;          which is on top of stack.
  2497                              <1> 	;
  2498                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2499                              <1> 
  2500                              <1> 	; 23/06/2015 (32 bit modifications)
  2501                              <1> 
  2502 00003B0C 891D[18650000]      <1> 	mov	[u.namep], ebx ; argument 1
  2503                              <1>         ; 18/10/2015
  2504 00003B12 890D[78650000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2505 00003B18 E8C4040000          <1> 	call	namei
  2506                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2507                              <1> 			     ; / named in sysexec call in r1
  2508                              <1> 	;jc	error
  2509                              <1> 		; br error9
  2510 00003B1D 731E                <1> 	jnc	short sysexec_0
  2511                              <1> 	;
  2512                              <1> 	; 'file not found !' error
  2513 00003B1F C705[4F650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2513 00003B27 0000                <1>
  2514 00003B29 E9B3F5FFFF          <1> 	jmp	error 
  2515                              <1> sysexec_not_exf:
  2516                              <1> 	; 'not executable file !' error
  2517 00003B2E C705[4F650000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2517 00003B36 0000                <1>
  2518 00003B38 E9A4F5FFFF          <1> 	jmp	error 
  2519                              <1> sysexec_0:
  2520 00003B3D E8B40C0000          <1> 	call	iget
  2521                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2522                              <1> 	; 03/02/2022
  2523 00003B42 F605[F4610000]10    <1> 	test	byte [i.flgs], 10h
  2524                              <1>         ;test	word [i.flgs], 10h
  2525                              <1> 		; bit $20,i.flgs / is file executable
  2526 00003B49 74E3                <1> 	jz	short sysexec_not_exf
  2527                              <1> 	;jz	error
  2528                              <1> 		; beq error9
  2529                              <1> 	;;
  2530 00003B4B E80A150000          <1> 	call	iopen
  2531                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2532                              <1> 			     ; / given in r1 (opens file)
  2533                              <1> 	; AX = i-number of the file
  2534                              <1> 	; 03/02/2022
  2535 00003B50 F605[F4610000]20    <1> 	test	byte [i.flgs], 20h
  2536                              <1> 	;test	word [i.flgs], 20h
  2537                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2538 00003B57 7415                <1> 	jz	short sysexec_1
  2539                              <1> 		; beq 1f
  2540 00003B59 803D[46650000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2541                              <1> 		; tstb u.uid / test user id
  2542 00003B60 760C                <1> 	jna	short sysexec_1
  2543                              <1> 		; beq 1f / super user
  2544 00003B62 8A0D[F7610000]      <1> 	mov	cl, [i.uid]
  2545 00003B68 880D[46650000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2546                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2547                              <1> 				 ; / as process user id
  2548                              <1> sysexec_1:
  2549                              <1> 	; 03/02/2022
  2550                              <1> 	; 18/10/2215
  2551                              <1> 	; 10/10/2015
  2552                              <1> 	; 21/07/2015, 24/07/2015
  2553                              <1> 	; 24/06/2015, 25/06/2015
  2554                              <1>         ; Moving arguments to the end of [u.upage]
  2555                              <1> 	; (by regarding page borders in user's memory space)
  2556                              <1> 	;
  2557                              <1> 	; 10/10/2015
  2558                              <1> 	; 21/07/2015
  2559 00003B6E 89E5                <1> 	mov	ebp, esp ; (**)
  2560                              <1> 	; 18/10/2015
  2561 00003B70 89EF                <1> 	mov 	edi, ebp
  2562 00003B72 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2563                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2564 00003B77 29CF                <1> 	sub	edi, ecx
  2565 00003B79 89FC                <1> 	mov	esp, edi
  2566 00003B7B 31C0                <1> 	xor	eax, eax
  2567 00003B7D A3[28650000]        <1> 	mov 	[u.nread], eax ; 0
  2568                              <1> 	; 03/02/2022
  2569                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2570                              <1> 	; may leave it with any value after an error))
  2571                              <1> 	;mov	[argc], ax
  2572 00003B82 A2[76650000]        <1> 	mov	[argc], al ; 0
  2573                              <1> 	;
  2574 00003B87 49                  <1> 	dec	ecx ; 256 - 1
  2575 00003B88 890D[24650000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2576                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2577                              <1> sysexec_2:
  2578 00003B8E 8B35[78650000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2579 00003B94 E864020000          <1> 	call	get_argp
  2580                              <1> 	;mov	ecx, 4 
  2581                              <1> 	; 03/02/2022
  2582 00003B99 31C9                <1> 	xor	ecx, ecx
  2583 00003B9B B104                <1> 	mov	cl, 4
  2584                              <1> sysexec_3:
  2585 00003B9D 21C0                <1> 	and	eax, eax
  2586 00003B9F 7456                <1> 	jz	short sysexec_6
  2587                              <1> 	; 18/10/2015
  2588 00003BA1 010D[78650000]      <1> 	add	[argv], ecx ; 4
  2589 00003BA7 66FF05[76650000]    <1> 	inc	word [argc]
  2590                              <1> 	;
  2591 00003BAE A3[20650000]        <1> 	mov	[u.base], eax
  2592                              <1>  	; 23/10/2015
  2593 00003BB3 66C705[5F650000]00- <1> 	mov	word [u.pcount], 0
  2593 00003BBB 00                  <1>
  2594                              <1> sysexec_4:
  2595 00003BBC E82D120000          <1> 	call	cpass ; get a character from user's core memory
  2596 00003BC1 750B                <1>         jnz	short sysexec_5
  2597                              <1> 		; (max. 255 chars + null)
  2598                              <1> 	; 18/10/2015
  2599 00003BC3 28C0                <1> 	sub 	al, al
  2600 00003BC5 AA                  <1> 	stosb
  2601 00003BC6 FF05[28650000]      <1> 	inc	dword [u.nread]
  2602 00003BCC EB29                <1> 	jmp	short sysexec_6
  2603                              <1> sysexec_5:
  2604 00003BCE AA                  <1> 	stosb
  2605 00003BCF 20C0                <1> 	and 	al, al
  2606 00003BD1 75E9                <1> 	jnz	short sysexec_4
  2607                              <1> 	;mov	ecx, 4
  2608                              <1> 	; 03/02/2022
  2609 00003BD3 29C9                <1> 	sub	ecx, ecx
  2610 00003BD5 B104                <1> 	mov	cl, 4
  2611                              <1> 	;cmp	[ncount], ecx ; 4
  2612                              <1> 	; 03/02/2022
  2613 00003BD7 66390D[74650000]    <1> 	cmp	[ncount], cx ; 4
  2614 00003BDE 72AE                <1> 	jb	short sysexec_2
  2615 00003BE0 8B35[70650000]      <1> 	mov	esi, [nbase]
  2616 00003BE6 010D[70650000]      <1> 	add	[nbase], ecx ; 4	
  2617 00003BEC 66290D[74650000]    <1> 	sub	[ncount], cx 
  2618 00003BF3 8B06                <1> 	mov	eax, [esi]
  2619 00003BF5 EBA6                <1> 	jmp	short sysexec_3
  2620                              <1> sysexec_6:
  2621                              <1> 	; 18/10/2015
  2622                              <1> 	; argument list transfer from user's core memory to
  2623                              <1> 	; kernel stack frame is OK here.
  2624                              <1> 	; [u.nread] = ; argument list length
  2625                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2626                              <1> 	;
  2627                              <1> 	; 18/10/2015
  2628                              <1>         ; 21/07/2015, 24/07/2015
  2629                              <1> 	; 25/06/2015, 02/07/2015
  2630                              <1> 	; 23/06/2015, 24/06/2015
  2631                              <1> 	;
  2632 00003BF7 8B1D[57650000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2633 00003BFD 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2634 00003BFF 740A                <1> 	jz	short sysexec_7
  2635 00003C01 A1[53650000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2636 00003C06 E806E9FFFF          <1> 	call	deallocate_page_dir
  2637                              <1> sysexec_7:
  2638 00003C0B E836E8FFFF          <1> 	call	make_page_dir
  2639                              <1> 	;jc	short sysexec_14
  2640                              <1> 	;jc	panic  ; allocation error 
  2641                              <1> 		       ; after a deallocation would be nonsence !?
  2642                              <1> 	; 03/02/2022
  2643 00003C10 7243                <1> 	jc	short sysexec_panic
  2644                              <1> 
  2645                              <1> 	; 24/07/2015
  2646                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2647                              <1> 	;     of the user's page directory
  2648                              <1> 	;     (It is needed for interrupts!)
  2649                              <1> 	; 18/10/2015
  2650 00003C12 8B15[38610000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2651 00003C18 8B02                <1> 	mov	eax, [edx] ; physical address of
  2652                              <1> 			   ; kernel's first page table (1st 4 MB)
  2653                              <1> 			   ; (PDE 0 of kernel's page directory)
  2654 00003C1A 8B15[53650000]      <1> 	mov 	edx, [u.pgdir]
  2655 00003C20 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2656                              <1> 	;
  2657                              <1> 	; 20/07/2015
  2658 00003C22 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2659                              <1> 	; 18/10/2015
  2660 00003C27 BE[68650000]        <1> 	mov	esi, pcore ; physical start address
  2661                              <1> sysexec_8:	
  2662 00003C2C B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2663 00003C31 E82EE8FFFF          <1> 	call	make_page_table
  2664                              <1> 	;jc	panic
  2665                              <1> 	; 03/02/2022
  2666 00003C36 721D                <1> 	jc	short sysexec_panic
  2667                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2668 00003C38 E835E8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2669                              <1> 	;jc	panic
  2670                              <1> 	; 03/02/2022
  2671 00003C3D 7216                <1> 	jc	short sysexec_panic
  2672                              <1> 	;
  2673 00003C3F 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2674                              <1> 	; ebx = virtual address (24/07/2015)
  2675                              <1> 	; 03/02/2022
  2676                              <1> 	;call 	add_to_swap_queue
  2677                              <1> 	; 18/10/2015
  2678 00003C41 81FE[6C650000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2679 00003C47 7411                <1> 	je	short sysexec_9 ; yes
  2680 00003C49 BE[6C650000]        <1> 	mov	esi, ecore ; physical address of the last page 
  2681                              <1> 	; 20/07/2015
  2682 00003C4E BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2683                              <1> 	; ebx = virtual end address + segment base address - 4K
  2684 00003C53 EBD7                <1>         jmp     short sysexec_8
  2685                              <1> 
  2686                              <1> sysexec_panic:
  2687                              <1> 	; 03/02/2022
  2688 00003C55 E949EDFFFF          <1> 	jmp	panic
  2689                              <1> 
  2690                              <1> sysexec_9:
  2691                              <1> 	; 18/10/2015
  2692                              <1> 	; 26/08/2015
  2693                              <1> 	; 25/06/2015
  2694                              <1> 	; move arguments from kernel stack to [ecore]
  2695                              <1> 	; (argument list/line will be copied from kernel stack
  2696                              <1> 	; frame to the last (stack) page of user's core memory)
  2697                              <1> 	; 18/10/2015
  2698 00003C5A 8B3D[6C650000]      <1> 	mov	edi, [ecore]
  2699 00003C60 81C700100000        <1> 	add	edi, PAGE_SIZE
  2700                              <1> 	;movzx	eax, word [argc]
  2701                              <1> 	; 03/02/2022
  2702 00003C66 31C0                <1> 	xor	eax, eax
  2703 00003C68 A0[76650000]        <1> 	mov	al, [argc]
  2704 00003C6D 08C0                <1> 	or	al, al
  2705                              <1> 	;or	eax, eax
  2706 00003C6F 7509                <1> 	jnz	short sysexec_10
  2707 00003C71 89FB                <1> 	mov 	ebx, edi
  2708 00003C73 83EB04              <1> 	sub	ebx, 4 
  2709 00003C76 8903                <1> 	mov	[ebx], eax ; 0
  2710 00003C78 EB43                <1> 	jmp 	short sysexec_13
  2711                              <1> sysexec_10:
  2712 00003C7A 8B0D[28650000]      <1> 	mov	ecx, [u.nread]
  2713                              <1> 	;mov 	esi, [argv]
  2714 00003C80 89E6                <1> 	mov	esi, esp ; start address of argument list
  2715 00003C82 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2716                              <1> 	
  2717                              <1> 	;;;;
  2718                              <1> 	; 09/05/2022
  2719                              <1> 	; (move edi -backward- to dword boundary)
  2720                              <1> 	; ((this will prevent 'general protection fault' error
  2721                              <1> 	;  as result of a lodsd or dword move instruction
  2722                              <1> 	;  at the end of argument list))
  2723 00003C84 83EF03              <1> 	sub	edi, 3
  2724 00003C87 83E7FC              <1> 	and	edi, ~3 ; (*)
  2725                              <1> 	;;;
  2726                              <1> 
  2727 00003C8A 89C2                <1> 	mov	edx, eax
  2728                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2729 00003C8C FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2730 00003C8E C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2731                              <1> 	; edx <= 128
  2732 00003C91 89FB                <1> 	mov	ebx, edi
  2733                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2734                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2735 00003C93 29D3                <1> 	sub 	ebx, edx
  2736 00003C95 89FA                <1> 	mov	edx, edi
  2737 00003C97 F3A4                <1> 	rep	movsb
  2738 00003C99 89D6                <1> 	mov 	esi, edx
  2739 00003C9B 89DF                <1> 	mov 	edi, ebx
  2740 00003C9D BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2741 00003CA2 2B15[6C650000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2742 00003CA8 AB                  <1> 	stosd	; eax = argument count	
  2743                              <1> sysexec_11:
  2744 00003CA9 89F0                <1> 	mov	eax, esi
  2745 00003CAB 01D0                <1> 	add	eax, edx
  2746 00003CAD AB                  <1> 	stosd  ; eax = virtual address
  2747 00003CAE FE0D[76650000]      <1> 	dec	byte [argc]
  2748 00003CB4 7407                <1> 	jz	short sysexec_13
  2749                              <1> sysexec_12:
  2750 00003CB6 AC                  <1> 	lodsb
  2751 00003CB7 20C0                <1> 	and	al, al
  2752 00003CB9 75FB                <1> 	jnz	short sysexec_12
  2753 00003CBB EBEC                <1> 	jmp	short sysexec_11
  2754                              <1> 	;
  2755                              <1> 	; 1:
  2756                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2757                              <1> 			     ; / pointers to arguments to be passed
  2758                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2759                              <1> 			      ; / u.quit = 1 take quit
  2760                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2761                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2762                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2763                              <1> 			       ; / system routine
  2764                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2765                              <1> 			       ; / set to take system routine
  2766                              <1> 		; mov $sstack,sp / stack space used during swapping
  2767                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2768                              <1> 		; mov $ecore,r5 / r5 has end of core
  2769                              <1> 		; mov $core,r4 / r4 has start of users core
  2770                              <1> 		; mov r4,u.base / u.base has start of users core
  2771                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2772                              <1> 	; 1:
  2773                              <1> 		; tst (r2)+ / argument char = "nul"
  2774                              <1> 		; bne 1b
  2775                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2776                              <1> 			  ; / end of argument pointer list
  2777                              <1> 	; 1:
  2778                              <1> 	     ; / move arguments to bottom of users core
  2779                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2780                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2781                              <1> 			    ; / ptr list
  2782                              <1> 		; blo 1f / branch to 1f when all arguments
  2783                              <1> 		       ; / are moved
  2784                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2785                              <1> 	; 2:
  2786                              <1> 		; tstb (r3)+
  2787                              <1> 		; bne 2b / scan argument for \0 (nul)
  2788                              <1> 
  2789                              <1> 	; 2:
  2790                              <1> 		; movb -(r3),-(r5) / move argument char 
  2791                              <1> 				 ; / by char starting at "ecore"
  2792                              <1> 		; cmp r3,(r2) / moved all characters in 
  2793                              <1> 			    ; / this argument
  2794                              <1> 		; bhi 2b / branch 2b if not
  2795                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2796                              <1> 			     ; / r5 has pointer to nth arg
  2797                              <1> 		; br 1b / string
  2798                              <1> 	; 1:
  2799                              <1> 		; clrb -(r5)
  2800                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2801                              <1> 			 ; / last word of argument strings
  2802                              <1> 		; mov $core,r2
  2803                              <1> 	
  2804                              <1> 	; 1: / move argument pointers into core following 
  2805                              <1> 	      ; / argument strings
  2806                              <1> 		; cmp r2,r4
  2807                              <1> 		; bhis 1f / branch to 1f when all pointers
  2808                              <1> 			; / are moved
  2809                              <1> 		; mov (r2)+,-(r5)
  2810                              <1> 		; br 1b
  2811                              <1> 	; 1:
  2812                              <1> 		; sub $core,r4 / gives number of arguments *2
  2813                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2814                              <1> 		       ; / the number of args stored
  2815                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2816                              <1> 			     ; / of the argument pointers
  2817                              <1> sysexec_13:
  2818                              <1> 	; 19/10/2015
  2819                              <1> 	; 18/10/2015
  2820                              <1> 	; 29/07/2015
  2821                              <1> 	; 24/07/2015, 25/07/2015
  2822                              <1> 	; 25/06/2015, 20/07/2015
  2823                              <1> 	; 23/06/2015, 24/06/2015
  2824                              <1> 	;
  2825                              <1> 	; moving arguments to [ecore] is OK here..
  2826                              <1> 	; 18/10/2015
  2827 00003CBD 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2828                              <1> 	; ebx = beginning addres of argument list pointers
  2829                              <1> 	;	in user's stack
  2830                              <1> 	; 19/10/2015
  2831 00003CBF 2B1D[6C650000]      <1> 	sub 	ebx, [ecore]
  2832 00003CC5 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2833                              <1> 			; end of core - 4096 (last page)
  2834                              <1> 			; (virtual address)
  2835 00003CCB 891D[78650000]      <1> 	mov	[argv], ebx
  2836 00003CD1 891D[2C650000]      <1> 	mov	[u.break], ebx ; available user memory
  2837                              <1> 	;
  2838 00003CD7 29C0                <1> 	sub	eax, eax
  2839 00003CD9 C705[24650000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2839 00003CE1 0000                <1>
  2840                              <1> 		; mov $14,u.count
  2841 00003CE3 C705[10650000]-     <1> 	mov	dword [u.fofp], u.off
  2841 00003CE9 [1C650000]          <1>
  2842                              <1> 		; mov $u.off,u.fofp
  2843 00003CED A3[1C650000]        <1> 	mov	[u.off], eax ; 0
  2844                              <1> 		; clr u.off / set offset in file to be read to zero
  2845                              <1> 	; 25/07/2015
  2846 00003CF2 A3[20650000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2847                              <1> 	; 25/06/2015 
  2848 00003CF7 66A1[E0640000]      <1> 	mov	ax, [ii]
  2849                              <1> 	; AX = i-number of the executable file
  2850 00003CFD E8C80C0000          <1> 	call	readi
  2851                              <1> 		; jsr r0,readi / read in first six words of 
  2852                              <1> 			; / user's file, starting at $core
  2853                              <1> 		; mov sp,r5 / put users stack address in r5
  2854                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2855                              <1> 				; / from r5 (leaves number of words
  2856                              <1> 				; / less 26 available for
  2857                              <1> 			     	; / program in user core
  2858                              <1> 		; mov r5,u.count /
  2859                              <1> 	; 25/06/2015
  2860 00003D02 8B0D[2C650000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2861 00003D08 890D[24650000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2862                              <1> 	;
  2863 00003D0E 8B0D[28650000]      <1> 	mov	ecx, [u.nread]
  2864 00003D14 890D[2C650000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2865 00003D1A 80F920              <1> 	cmp	cl, 32
  2866 00003D1D 7540                <1>         jne     short sysexec_15
  2867                              <1> 	;:
  2868                              <1> 	; 25/06/2015
  2869                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2870                              <1> 	; 18/10/2015
  2871 00003D1F 8B35[68650000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2872                              <1> 		             ; (phys. start addr. of the exec. file)
  2873 00003D25 AD                  <1> 	lodsd
  2874 00003D26 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  2875 00003D2A 7533                <1> 	jne	short sysexec_15
  2876                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2877                              <1> 			      ; / if file is standard a.out format
  2878                              <1> 		; bne 1f / branch, if not standard format
  2879 00003D2C AD                  <1> 	lodsd
  2880 00003D2D 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2881 00003D2F AD                  <1> 	lodsd
  2882 00003D30 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2883                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2884                              <1> 		              ; / number of bytes in program text	
  2885                              <1> 		; sub $14,r5 / subtract 12
  2886 00003D32 89CB                <1> 	mov	ebx, ecx
  2887                              <1> 	;
  2888                              <1> 	; 25/06/2015
  2889                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2890                              <1> 	;	and SINGLIX operating systems (as code template).
  2891                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2892                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2893                              <1> 	;	Overrun is not possible for current version. 	
  2894                              <1> 	;
  2895 00003D34 AD                  <1> 	lodsd	
  2896 00003D35 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2897 00003D37 3B1D[24650000]      <1> 	cmp	ebx, [u.count]
  2898 00003D3D 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2899                              <1> 	;
  2900                              <1> 	; 24/07/2015
  2901                              <1> 	; add bss section size to [u.break]
  2902 00003D3F 0105[2C650000]      <1> 	add 	[u.break], eax
  2903                              <1> 	;
  2904 00003D45 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2905                              <1> 	;cmp	ecx, [u.count]
  2906                              <1> 	;jnb	short sysexec_16
  2907                              <1> 		; cmp r5,u.count /
  2908                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2909 00003D48 890D[24650000]      <1> 	mov	[u.count], ecx ; required read count
  2910                              <1> 		; mov r5,u.count
  2911                              <1> 	;
  2912 00003D4E EB2A                <1> 	jmp	short sysexec_16
  2913                              <1> 	;
  2914                              <1> sysexec_14:
  2915                              <1> 	; 23/06/2015
  2916                              <1> 	; insufficient (out of) memory
  2917 00003D50 C705[4F650000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2917 00003D58 0000                <1>
  2918 00003D5A E982F3FFFF          <1> 	jmp	error
  2919                              <1> 	;
  2920                              <1> sysexec_15:
  2921                              <1> 	; 25/06/2015
  2922 00003D5F 0FB715[F8610000]    <1>         movzx   edx, word [i.size] ; file size
  2923 00003D66 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2924 00003D68 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2925 00003D6A 01D1                <1> 	add	ecx, edx ; [i.size]
  2926 00003D6C 3B0D[24650000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2927 00003D72 77DC                <1> 	ja	short sysexec_14
  2928 00003D74 8915[24650000]      <1> 	mov	[u.count], edx
  2929                              <1> sysexec_16:
  2930 00003D7A 66A1[E0640000]      <1> 	mov	ax, [ii] ; i-number
  2931 00003D80 E8450C0000          <1> 	call	readi
  2932                              <1> 		; add core+10,u.nread / add size of user data area 
  2933                              <1> 		                    ; / to u.nread
  2934                              <1> 		; br 2f
  2935                              <1> 	; 1:
  2936                              <1> 		; jsr r0,readi / read in rest of file
  2937                              <1> 	; 2:
  2938 00003D85 8B0D[28650000]      <1> 	mov	ecx, [u.nread]
  2939 00003D8B 010D[2C650000]      <1> 	add	[u.break], ecx
  2940                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2941                              <1> 				    ; / user code
  2942                              <1> 		; add $core+14,u.break / plus data area
  2943                              <1> sysexec_17: ; 20/07/2015
  2944                              <1> 	; 03/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2945                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2946                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2947                              <1> 	;;mov	ax, [ii] ; i-number
  2948                              <1> 	;call	iclose
  2949                              <1> 	;	; jsr r0,iclose / does nothing
  2950 00003D91 31C0                <1>         xor     eax, eax
  2951 00003D93 FEC0                <1> 	inc	al
  2952 00003D95 66A3[3E650000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2953 00003D9B 66A3[40650000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2954                              <1> 	; 02/07/2015
  2955 00003DA1 833D[57650000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  2956 00003DA8 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  2957                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  2958 00003DAA 8B15[38610000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  2959 00003DB0 8915[57650000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  2960                              <1> sysexec_18:
  2961                              <1> 	; 18/10/2015
  2962                              <1> 	; 05/08/2015
  2963                              <1> 	; 29/07/2015
  2964 00003DB6 8B2D[78650000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  2965                              <1> 			    ; list pointers (argument count)
  2966 00003DBC FA                  <1> 	cli
  2967 00003DBD 8B25[D4600000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  2968                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  2969                              <1> 			    ; for this process	 
  2970                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  2971                              <1> 	;xor	eax, eax ; 0
  2972 00003DC3 FEC8                <1> 	dec	al ; eax = 0
  2973 00003DC5 66BA2300            <1> 	mov	dx, UDATA
  2974 00003DC9 6652                <1> 	push	dx  ; user's stack segment
  2975 00003DCB 55                  <1> 	push	ebp ; user's stack pointer
  2976                              <1> 		    ; (points to number of arguments)
  2977 00003DCC FB                  <1> 	sti
  2978 00003DCD 9C                  <1> 	pushfd	; EFLAGS
  2979                              <1> 		; Set IF for enabling interrupts in user mode	
  2980                              <1> 	;or	dword [esp], 200h 
  2981                              <1> 	;
  2982                              <1> 	;mov	bx, UCODE
  2983                              <1> 	;push	bx ; user's code segment
  2984 00003DCE 6A1B                <1> 	push	UCODE
  2985                              <1> 	;push	0
  2986 00003DD0 50                  <1> 	push	eax ; EIP (=0) - start address -	
  2987                              <1> 		; clr -(r5) / popped into ps when rti in 
  2988                              <1> 			  ; / sysrele is executed
  2989                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  2990                              <1> 		                ; / in sysrele is executed
  2991                              <1> 		;mov r5,0f / load second copyz argument
  2992                              <1> 		;tst -(r5) / decrement r5
  2993 00003DD1 8925[F8640000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  2994                              <1> 	; 05/08/2015
  2995                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  2996                              <1> 	; ('push dx' would cause to general protection fault, 
  2997                              <1> 	; after 'pop ds' etc.)
  2998                              <1> 	;
  2999                              <1> 	;; push dx ; ds (UDATA)
  3000                              <1> 	;; push dx ; es (UDATA)
  3001                              <1> 	;; push dx ; fs (UDATA)
  3002                              <1> 	;; push dx ; gs (UDATA)
  3003                              <1> 	;
  3004                              <1> 	; This is a trick to prevent general protection fault
  3005                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3006 00003DD7 8EC2                <1> 	mov 	es, dx ; UDATA
  3007 00003DD9 06                  <1> 	push 	es ; ds (UDATA)
  3008 00003DDA 06                  <1> 	push 	es ; es (UDATA)
  3009 00003DDB 06                  <1> 	push 	es ; fs (UDATA)
  3010 00003DDC 06                  <1> 	push	es ; gs (UDATA)
  3011 00003DDD 66BA1000            <1> 	mov	dx, KDATA
  3012 00003DE1 8EC2                <1> 	mov	es, dx
  3013                              <1> 	;
  3014                              <1> 	;; pushad simulation
  3015 00003DE3 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3016 00003DE5 50                  <1> 	push	eax ; eax (0)
  3017 00003DE6 50                  <1> 	push	eax ; ecx (0)
  3018 00003DE7 50                  <1> 	push	eax ; edx (0)
  3019 00003DE8 50                  <1> 	push	eax ; ebx (0)
  3020 00003DE9 55                  <1> 	push	ebp ; esp before pushad
  3021 00003DEA 50                  <1> 	push	eax ; ebp (0)
  3022 00003DEB 50                  <1> 	push	eax ; esi (0)		
  3023 00003DEC 50                  <1> 	push	eax ; edi (0)	
  3024                              <1> 	;
  3025 00003DED A3[00650000]        <1> 	mov	[u.r0], eax ; eax = 0
  3026 00003DF2 8925[FC640000]      <1> 	mov	[u.usp], esp
  3027                              <1> 		; mov r5,u.r0 /
  3028                              <1> 		; sub $16.,r5 / skip 8 words
  3029                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3030                              <1> 		;             / effectively zeroes all regs
  3031                              <1> 			    ; / when sysrele is executed
  3032                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3033                              <1> 		; clr u.break
  3034                              <1> 		; mov r5,sp / point sp to user's stack
  3035                              <1> 	;
  3036 00003DF8 E906F3FFFF          <1> 	jmp	sysret0
  3037                              <1> 	;jmp	sysret
  3038                              <1> 		; br sysret3 / return to core image at $core
  3039                              <1> 
  3040                              <1> get_argp:
  3041                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  3042                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3043                              <1> 	; 18/10/2015 (nbase, ncount)
  3044                              <1> 	; 21/07/2015
  3045                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3046                              <1> 	; Get (virtual) address of argument from user's core memory
  3047                              <1> 	;
  3048                              <1> 	; INPUT:
  3049                              <1> 	;	esi = virtual address of argument pointer
  3050                              <1> 	; OUTPUT:
  3051                              <1> 	;	eax = virtual address of argument
  3052                              <1> 	;
  3053                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3054                              <1> 	;
  3055 00003DFD 833D[57650000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3056                              <1> 				    ; (the caller is kernel)
  3057                              <1>         ;jna	short get_argpk
  3058                              <1> 	; 03/02/2022
  3059 00003E04 7719                <1> 	ja	short get_argp5
  3060                              <1> get_argpk:
  3061                              <1> 	; Argument is in kernel's memory space
  3062 00003E06 66C705[74650000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3062 00003E0E 10                  <1>
  3063 00003E0F 8935[70650000]      <1> 	mov	[nbase], esi
  3064 00003E15 8305[70650000]04    <1> 	add	dword [nbase], 4
  3065 00003E1C 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3066 00003E1E C3                  <1> 	retn
  3067                              <1> get_argp5:
  3068 00003E1F 89F3                <1>      	mov	ebx, esi
  3069 00003E21 E8A3E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3070 00003E26 7257                <1>         jc	short get_argp_err ; 03/02/2022 (short jump)
  3071 00003E28 A3[70650000]        <1> 	mov 	[nbase], eax ; physical address	
  3072 00003E2D 66890D[74650000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3073 00003E34 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3074                              <1> 	;cmp	cx, ax ; 4
  3075                              <1> 	; 03/02/2022
  3076 00003E39 39C1                <1> 	cmp	ecx, eax
  3077 00003E3B 734C                <1> 	jnb	short get_argp2
  3078 00003E3D 89F3                <1> 	mov	ebx, esi
  3079 00003E3F 01CB                <1> 	add	ebx, ecx
  3080 00003E41 E883E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3081 00003E46 7237                <1> 	jc	short get_argp_err
  3082                              <1> 	;push	esi
  3083 00003E48 89C6                <1> 	mov	esi, eax
  3084 00003E4A 66870D[74650000]    <1> 	xchg	cx, [ncount]
  3085 00003E51 8735[70650000]      <1> 	xchg	esi, [nbase]
  3086 00003E57 B504                <1> 	mov	ch, 4
  3087 00003E59 28CD                <1> 	sub	ch, cl
  3088                              <1> get_argp0:
  3089 00003E5B AC                  <1> 	lodsb
  3090                              <1> 	;push	ax
  3091                              <1> 	; 03/02/2022
  3092 00003E5C 50                  <1> 	push	eax
  3093 00003E5D FEC9                <1> 	dec	cl
  3094 00003E5F 75FA                <1>         jnz     short get_argp0
  3095 00003E61 8B35[70650000]      <1> 	mov	esi, [nbase]
  3096                              <1> 	; 21/07/2015
  3097 00003E67 0FB6C5              <1> 	movzx	eax, ch
  3098 00003E6A 0105[70650000]      <1> 	add	[nbase], eax
  3099 00003E70 662905[74650000]    <1> 	sub	[ncount], ax
  3100                              <1> get_argp1:
  3101 00003E77 AC                  <1> 	lodsb
  3102 00003E78 FECD                <1> 	dec	ch
  3103 00003E7A 7423                <1>         jz      short get_argp3
  3104                              <1>         ;push	ax
  3105                              <1> 	; 03/02/2022
  3106 00003E7C 50                  <1> 	push	eax
  3107 00003E7D EBF8                <1> 	jmp     short get_argp1
  3108                              <1> get_argp_err:
  3109 00003E7F A3[4F650000]        <1> 	mov	[u.error], eax
  3110 00003E84 E958F2FFFF          <1> 	jmp	error
  3111                              <1> get_argp2:
  3112                              <1> 	; 21/07/2015
  3113                              <1> 	;mov	eax, 4
  3114 00003E89 8B15[70650000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3115 00003E8F 0105[70650000]      <1> 	add	[nbase], eax
  3116 00003E95 662905[74650000]    <1> 	sub	[ncount], ax
  3117                              <1> 	;
  3118 00003E9C 8B02                <1> 	mov	eax, [edx]
  3119 00003E9E C3                  <1> 	retn
  3120                              <1> get_argp3:
  3121 00003E9F B103                <1> 	mov	cl, 3
  3122                              <1> get_argp4:
  3123 00003EA1 C1E008              <1> 	shl	eax, 8
  3124                              <1> 	;pop	dx
  3125                              <1> 	; 03/02/2022
  3126 00003EA4 5A                  <1> 	pop	edx
  3127 00003EA5 88D0                <1> 	mov 	al, dl
  3128 00003EA7 E2F8                <1>         loop    get_argp4
  3129                              <1> 	;pop	esi
  3130 00003EA9 C3                  <1> 	retn	
  3131                              <1> 
  3132                              <1> sysfstat:
  3133                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3134                              <1> 	;	([idev] return in eax)
  3135                              <1> 	;	0 = root device
  3136                              <1> 	;	1 = mounted device (>0)
  3137                              <1> 	; 03/02/2022
  3138                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3139                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3140                              <1> 	;
  3141                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3142                              <1> 	; on open files instead of files given by name. It puts the
  3143                              <1> 	; buffer address on the stack, gets the i-number and
  3144                              <1> 	; checks to see if the file is open for reading or writing.
  3145                              <1> 	; If the file is open for writing (i-number is negative)
  3146                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3147                              <1> 	; is made.	
  3148                              <1> 	;
  3149                              <1> 	; Calling sequence:
  3150                              <1> 	;	sysfstat; buf
  3151                              <1> 	; Arguments:
  3152                              <1> 	;	buf - buffer address
  3153                              <1> 	;
  3154                              <1> 	; Inputs: *u.r0 - file descriptor
  3155                              <1> 	; Outputs: buffer is loaded with file information
  3156                              <1> 	; ...............................................................
  3157                              <1> 	;				
  3158                              <1> 	; Retro UNIX 8086 v1 modification:
  3159                              <1> 	;       'sysfstat' system call has two arguments; so,
  3160                              <1> 	;	* 1st argument, file descriptor is in BX register
  3161                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3162                              <1> 
  3163                              <1> 	; / set status of open file
  3164                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3165 00003EAA 51                  <1> 	push	ecx
  3166                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3167                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3168                              <1> 		; jsr r0,getf / get the files i-number
  3169                              <1> 	; BX = file descriptor (file number)
  3170 00003EAB E8FE000000          <1> 	call	getf1
  3171                              <1> 	; 03/02/2022
  3172 00003EB0 21C0                <1> 	and	eax, eax
  3173                              <1> 	;and	ax, ax ; i-number of the file
  3174                              <1> 		; tst	r1 / is it 0?
  3175                              <1> 	;jz	error
  3176                              <1> 		; beq error3 / yes, error
  3177 00003EB2 750F                <1> 	jnz	short sysfstat1
  3178 00003EB4 C705[4F650000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3178 00003EBC 0000                <1>
  3179 00003EBE E91EF2FFFF          <1> 	jmp	error
  3180                              <1> sysfstat1:
  3181 00003EC3 80FC80              <1> 	cmp	ah, 80h
  3182 00003EC6 7222                <1>         jb      short sysstat1
  3183                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3184 00003EC8 66F7D8              <1> 	neg	ax
  3185                              <1> 		; neg r1 / make it positive, then branch
  3186 00003ECB EB1D                <1> 	jmp	short sysstat1
  3187                              <1> 		; br 1f / to 1f
  3188                              <1> sysstat:
  3189                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3190                              <1> 	;	([idev] return in eax)
  3191                              <1> 	;	0 = root device
  3192                              <1> 	;	1 = mounted device (>0)
  3193                              <1> 	; 03/02/2022
  3194                              <1> 	; 18/10/2015
  3195                              <1> 	; 07/10/2015
  3196                              <1> 	; 02/09/2015
  3197                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3198                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3199                              <1> 	;
  3200                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3201                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3202                              <1> 	; long and information about the file placed in it.	
  3203                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3204                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3205                              <1> 	; is then loaded and the results are given in the UNIX
  3206                              <1> 	; Programmers Manual sysstat (II).	
  3207                              <1> 	;
  3208                              <1> 	; Calling sequence:
  3209                              <1> 	;	sysstat; name; buf
  3210                              <1> 	; Arguments:
  3211                              <1> 	;	name - points to the name of the file
  3212                              <1> 	;	buf - address of a 34 bytes buffer
  3213                              <1> 	; Inputs: -
  3214                              <1> 	; Outputs: buffer is loaded with file information
  3215                              <1> 	; ...............................................................
  3216                              <1> 	;				
  3217                              <1> 	; Retro UNIX 8086 v1 modification: 
  3218                              <1> 	;       'sysstat' system call has two arguments; so,
  3219                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3220                              <1> 	;	to get sysstat system call arguments from the user;
  3221                              <1> 	;	* 1st argument, name is pointed to by BX register
  3222                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3223                              <1> 	;
  3224                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3225                              <1> 	;	      arguments which were in these registers;
  3226                              <1> 	;	      but, it returns by putting the 1st argument
  3227                              <1> 	;	      in 'u.namep' and the 2nd argument
  3228                              <1> 	;	      on top of stack. (1st argument is offset of the
  3229                              <1> 	;	      file/path name in the user's program segment.)		 	
  3230                              <1> 	
  3231                              <1> 	; / ; name of file; buffer - get files status
  3232                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3233 00003ECD 891D[18650000]      <1> 	mov	[u.namep], ebx
  3234 00003ED3 51                  <1> 	push	ecx
  3235 00003ED4 E808010000          <1> 	call	namei
  3236                              <1> 		; jsr r0,namei / get the i-number for the file
  3237                              <1> 	;jc	error
  3238                              <1> 		; br error3 / no such file, error
  3239 00003ED9 730F                <1> 	jnc	short sysstat1
  3240                              <1> 	; pop 	ecx
  3241                              <1> sysstat_err0:
  3242                              <1> 	; 'file not found !' error
  3243 00003EDB C705[4F650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3243 00003EE3 0000                <1>
  3244 00003EE5 E9F7F1FFFF          <1> 	jmp	error
  3245                              <1> 
  3246                              <1> ;statx: db 0
  3247                              <1> 
  3248                              <1> sysstat1: ; 1:
  3249 00003EEA E807090000          <1> 	call	iget
  3250                              <1> 		; jsr r0,iget / get the i-node into core
  3251                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3252                              <1> 	; 02/09/2015
  3253 00003EEF 8F05[20650000]      <1> 	pop	dword [u.base]
  3254                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3255 00003EF5 E861000000          <1> 	call	sysstat_gpa ; get physical address
  3256 00003EFA 730A                <1> 	jnc 	short sysstat2
  3257                              <1> sysstat_err1:
  3258 00003EFC A3[4F650000]        <1> 	mov	dword [u.error], eax ; error code
  3259 00003F01 E9DBF1FFFF          <1> 	jmp	error
  3260                              <1> sysstat2:
  3261 00003F06 A0[E0640000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3262 00003F0B AA                  <1> 	stosb
  3263 00003F0C FF05[20650000]      <1> 	inc 	dword [u.base]
  3264                              <1> 	;dec 	cx
  3265                              <1> 	; 03/02/2022
  3266 00003F12 49                  <1> 	dec	ecx
  3267 00003F13 7505                <1> 	jnz	short sysstat3
  3268 00003F15 E841000000          <1> 	call	sysstat_gpa
  3269                              <1> 	;jc	short sysstat_err1
  3270                              <1> sysstat3:
  3271 00003F1A A0[E1640000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3272 00003F1F AA                  <1> 	stosb
  3273                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3274 00003F20 FF05[20650000]      <1> 	inc 	dword [u.base]
  3275                              <1> 	;;dec 	word [u.pcount]
  3276                              <1> 	;dec	cx
  3277                              <1> 	; 03/02/2022
  3278 00003F26 49                  <1> 	dec	ecx
  3279 00003F27 7505                <1> 	jnz	short sysstat4
  3280 00003F29 E82D000000          <1> 	call	sysstat_gpa
  3281                              <1> 	;jc	short sysstat_err1	
  3282                              <1> sysstat4:
  3283 00003F2E BE[F4610000]        <1> 	mov	esi, inode
  3284                              <1> 		; mov $inode,r2 / r2 points to i-node
  3285                              <1> sysstat5: ; 1:
  3286 00003F33 A4                  <1> 	movsb
  3287                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3288 00003F34 FF05[20650000]      <1> 	inc 	dword [u.base]
  3289                              <1> 	;;dec 	word [u.pcount]
  3290                              <1> 	;dec	cx
  3291                              <1> 	; 03/02/2022
  3292 00003F3A 49                  <1> 	dec	ecx
  3293 00003F3B 7505                <1> 	jnz	short sysstat6
  3294 00003F3D E819000000          <1> 	call	sysstat_gpa
  3295                              <1> 	;jc	short sysstat_err1
  3296                              <1> sysstat6:		
  3297 00003F42 81FE[14620000]      <1> 	cmp	esi, inode + 32
  3298                              <1> 		; cmp r2,$inode+32 / done?
  3299 00003F48 75E9                <1> 	jne	short sysstat5
  3300                              <1> 		; bne 1b / no, go back
  3301                              <1> 
  3302                              <1> 	;;;
  3303                              <1> 	; 09/05/2022
  3304                              <1> 	;*** additional feature *** -retro unix only- 
  3305                              <1> 	;
  3306                              <1> 	; !! return device number -of current inode- in eax !!
  3307                              <1> 	;
  3308                              <1> 	; (modification reason/purpose:
  3309                              <1> 	; to improve 'pwd' command's pathname output/result
  3310                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3311                              <1> 	; error due to same inode numbers in root file system
  3312                              <1> 	; and mounted file system.)
  3313                              <1> 	;
  3314 00003F4A 29C0                <1> 	sub	eax, eax
  3315 00003F4C A0[E2640000]        <1> 	mov	al, [idev] ; [cdev]
  3316 00003F51 A3[00650000]        <1> 	mov	[u.r0], eax
  3317                              <1> 	;;;  
  3318                              <1> 
  3319 00003F56 E9A6F1FFFF          <1> 	jmp	sysret
  3320                              <1> 		; br sysret3 / return through sysret
  3321                              <1> 	;
  3322                              <1> sysstat_gpa: ; get physical address of file status buffer
  3323                              <1> 	; 02/09/2015
  3324 00003F5B 8B1D[20650000]      <1> 	mov 	ebx, [u.base]
  3325                              <1> 	; 07/10/2015
  3326 00003F61 E863E8FFFF          <1> 	call	get_physical_addr ; get physical address
  3327                              <1> 	;jc	short sysstat_gpa1
  3328 00003F66 7294                <1> 	jc	short sysstat_err1
  3329                              <1> 	; 18/10/2015
  3330 00003F68 89C7                <1> 	mov	edi, eax ; physical address
  3331                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3332                              <1> ;sysstat_gpa1:
  3333 00003F6A C3                  <1> 	retn
  3334                              <1> 
  3335                              <1> fclose:
  3336                              <1> 	; 03/02/2022
  3337                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3338                              <1> 	;            (32 bit offset pointer modification)
  3339                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3340                              <1> 	;
  3341                              <1> 	; Given the file descriptor (index to the u.fp list)
  3342                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3343                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3344                              <1> 	; u.fp list is cleared. If all the processes that opened
  3345                              <1> 	; that file close it, then fsp etry is freed and the file
  3346                              <1> 	; is closed. If not a return is taken. 
  3347                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3348                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3349                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3350                              <1> 	; a check is made to see if the file is special.	
  3351                              <1> 	;
  3352                              <1> 	; INPUTS ->
  3353                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3354                              <1> 	;    u.fp - list of entries in the fsp table
  3355                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3356                              <1> 	; OUTPUTS ->
  3357                              <1> 	;    r1 - contains the same file descriptor
  3358                              <1> 	;    r2 - contains i-number
  3359                              <1> 	;
  3360                              <1> 	; ((AX = R1))
  3361                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3362                              <1> 	;
  3363                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3364                              <1> 	;              if i-number of the file is 0. (error)  	
  3365                              <1> 
  3366                              <1> 	;movzx	edx, ax ; **
  3367                              <1> 	; 03/02/2022
  3368                              <1> 	;movzx	edx, al
  3369 00003F6B 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 03/02/2022
  3370 00003F6D 50                  <1> 	push	eax ; ***
  3371                              <1> 	;push	ax ; ***
  3372                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3373                              <1> 			     ; / the index to u.fp list)
  3374 00003F6E E839000000          <1> 	call	getf
  3375                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3376                              <1> 			    ; / cdev has device =, u.fofp 
  3377                              <1> 			    ; / points to 3rd word of fsp entry
  3378 00003F73 6683F801            <1> 	cmp	ax, 1 ; r1
  3379                              <1> 		; tst r1 / is i-number 0?
  3380 00003F77 7231                <1> 	jb	short fclose_2
  3381                              <1> 		; beq 1f / yes, i-node not active so return
  3382                              <1> 		; tst (r0)+ / no, jump over error return
  3383 00003F79 89D3                <1> 	mov	ebx, edx ; **
  3384                              <1> 	; 03/02/2022
  3385 00003F7B 89C2                <1> 	mov	edx, eax ; *
  3386                              <1> 	;mov 	dx, ax ; *
  3387                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3388                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3389                              <1> 			    ; / which is index to u.fp ; **
  3390 00003F7D C683[06650000]00    <1> 	mov	byte [ebx+u.fp], 0
  3391                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3392 00003F84 8B1D[10650000]      <1> 	mov	ebx, [u.fofp]
  3393                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3394                              <1> fclose_0:
  3395 00003F8A FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3396                              <1> 		; decb 2(r1) / decrement the number of processes 
  3397                              <1> 			   ; / that have opened the file
  3398 00003F8D 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3399                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3400                              <1> 	;
  3401                              <1> 	; 03/02/2022
  3402 00003F8F 52                  <1> 	push	edx ; *
  3403                              <1> 	;push	dx ; *
  3404                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3405                              <1> 	;xor	ax, ax ; 0
  3406                              <1> 	; 03/02/2022
  3407 00003F90 31C0                <1> 	xor	eax, eax
  3408 00003F92 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3409                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3410 00003F96 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3411                              <1> 		; tstb	3(r1) / has this file been deleted
  3412 00003F99 20C0                <1> 	and	al, al
  3413 00003F9B 7407                <1> 	jz	short fclose_1
  3414                              <1> 		; beq 2f / no, branch
  3415                              <1> 	; 03/02/2022
  3416 00003F9D 89D0                <1> 	mov	eax, edx
  3417                              <1> 	;mov	ax, dx ; *
  3418                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3419                              <1> 	; AX = inode number
  3420 00003F9F E8A7040000          <1> 	call	anyi
  3421                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3422                              <1> 			    ; / check if file appears in fsp again
  3423                              <1> fclose_1: ; 2:
  3424                              <1> 	; 03/02/2022
  3425 00003FA4 58                  <1> 	pop	eax ; * 
  3426                              <1> 	;pop	ax ; *
  3427                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3428 00003FA5 E8EF110000          <1> 	call	iclose ; close if it is special file 
  3429                              <1> 		; jsr r0,iclose / check to see if its a special file
  3430                              <1> fclose_2: ; 1:
  3431                              <1> 	; 03/02/2022
  3432 00003FAA 58                  <1> 	pop	eax ; ***
  3433                              <1> 	;pop	ax ; ***
  3434                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3435 00003FAB C3                  <1> 	retn
  3436                              <1> 		; rts r0
  3437                              <1> 
  3438                              <1> getf:	; / get the device number and the i-number of an open file
  3439                              <1> 	; 03/02/2022
  3440                              <1> 	; 13/05/2015
  3441                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3442                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3443                              <1> 	;
  3444 00003FAC 89C3                <1> 	mov	ebx, eax
  3445                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3446                              <1> 	; 03/02/2022
  3447 00003FAE 29C0                <1> 	sub	eax, eax
  3448                              <1> 	;
  3449 00003FB0 83FB0A              <1> 	cmp	ebx, 10
  3450                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3451 00003FB3 732B                <1>         jnb	short getf2 ; 13/05/2015
  3452                              <1> 	;jnb	error
  3453                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3454                              <1> 			    ; / index in fsp table
  3455                              <1> 	; 03/02/2022
  3456 00003FB5 8A83[06650000]      <1> 	mov	al, [ebx+u.fp]
  3457                              <1> 	;mov	bl, [ebx+u.fp]
  3458                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3459                              <1> 		                  ; / in fsp table
  3460                              <1> 	; 03/02/2022
  3461 00003FBB 08C0                <1> 	or	al, al
  3462 00003FBD 7421                <1> 	jz	short getf2
  3463                              <1> 	;or	bl, bl
  3464                              <1> 	;jnz	short getf3
  3465                              <1> 	;;jz	short getf4
  3466                              <1> 		; beq 1f / if its zero return
  3467                              <1> ;getf2:
  3468                              <1> ;	; 'File not open !' error (ax=0)
  3469                              <1> ;	sub	eax, eax
  3470                              <1> ;	retn
  3471                              <1> 
  3472                              <1> getf3:	
  3473                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3474                              <1> 	;
  3475                              <1> 	; 'fsp' table (10 bytes/entry)
  3476                              <1> 	; bit 15				   bit 0
  3477                              <1> 	; ---|-------------------------------------------
  3478                              <1> 	; r/w|		i-number of open file
  3479                              <1> 	; ---|-------------------------------------------
  3480                              <1> 	;		   device number
  3481                              <1> 	; -----------------------------------------------
  3482                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3483                              <1> 	; -----------------------------------------------
  3484                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3485                              <1> 	; ----------------------|------------------------
  3486                              <1> 	;  flag that says file 	| number of processes
  3487                              <1> 	;   has been deleted	| that have file open 
  3488                              <1> 	; ----------------------|------------------------
  3489                              <1> 	;
  3490                              <1> 	;mov	eax, 10
  3491                              <1> 	; 03/02/2022
  3492 00003FBF B30A                <1> 	mov	bl, 10
  3493 00003FC1 F6E3                <1> 	mul	bl
  3494 00003FC3 BB[BE620000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3495 00003FC8 01C3                <1> 	add	ebx, eax
  3496                              <1> 		; asl r1
  3497                              <1> 		; asl r1 / multiply by 8 to get index into 
  3498                              <1> 		       ; / fsp table entry
  3499                              <1> 		; asl r1
  3500                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3501                              <1> 			      ; / in the fsp entry
  3502 00003FCA 891D[10650000]      <1> 	mov	[u.fofp], ebx
  3503                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3504                              <1> 			      ; / in fsp entry in u.fofp
  3505 00003FD0 4B                  <1> 	dec	ebx
  3506 00003FD1 4B                  <1> 	dec	ebx
  3507                              <1> 	;mov	al, [ebx]
  3508 00003FD2 668B03              <1> 	mov	ax, [ebx]
  3509                              <1> 	;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3510 00003FD5 66A3[E4640000]      <1> 	mov	[cdev], ax ; ;;in fact (!) 
  3511                              <1> 			     ;;dev number is in 1 byte
  3512                              <1> 		; mov -(r1),cdev / remove the device number  cdev
  3513 00003FDB 4B                  <1> 	dec	ebx
  3514 00003FDC 4B                  <1> 	dec	ebx
  3515 00003FDD 668B03              <1> 	mov	ax, [ebx]
  3516                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3517                              <1> getf2:	; 03/02/2022
  3518                              <1> getf4:	; 1:
  3519 00003FE0 C3                  <1> 	retn
  3520                              <1> 		; rts r0
  3521                              <1> 
  3522                              <1> namei:
  3523                              <1> 	; 15/05/2022
  3524                              <1> 	; 14/05/2022 (mounted directory path, '..' method)
  3525                              <1> 	; 03/02/2022
  3526                              <1> 	; 18/10/2015 (nbase, ncount)
  3527                              <1> 	; 12/10/2015
  3528                              <1> 	; 21/08/2015
  3529                              <1> 	; 18/07/2015
  3530                              <1> 	; 02/07/2015
  3531                              <1> 	; 17/06/2015
  3532                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3533                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3534                              <1> 	;
  3535                              <1> 	; 'namei' takes a file path name and returns i-number of
  3536                              <1> 	; the file in the current directory or the root directory
  3537                              <1> 	; (if the first character of the pathname is '/').	
  3538                              <1> 	;
  3539                              <1> 	; INPUTS ->
  3540                              <1> 	;    u.namep - points to a file path name
  3541                              <1> 	;    u.cdir - i-number of users directory
  3542                              <1> 	;    u.cdev - device number on which user directory resides	
  3543                              <1> 	; OUTPUTS ->
  3544                              <1> 	;    r1 - i-number of file
  3545                              <1> 	;    cdev
  3546                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3547                              <1> 	;               occurs in the search for file path name.
  3548                              <1> 	;	        If no match u.dirb points to the end of 
  3549                              <1> 	;               the directory and r1 = i-number of the current
  3550                              <1> 	;	        directory.	
  3551                              <1> 	; ((AX = R1))
  3552                              <1> 	;
  3553                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3554                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3555                              <1> 	;
  3556                              <1> 
  3557 00003FE1 66A1[04650000]      <1> 	mov	ax, [u.cdir]
  3558                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3559                              <1> 			      ; / in r1
  3560 00003FE7 668B15[44650000]    <1> 	mov	dx, [u.cdrv]
  3561 00003FEE 668915[E4640000]    <1> 	mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3562                              <1> 				    ; device/drive number is in 1 byte, 
  3563                              <1> 				    ; not in 1 word!
  3564                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3565                              <1> 				; / into cdev
  3566                              <1> 	; 12/10/2015
  3567                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3568                              <1>       	 ; convert virtual (pathname) addr to physical address
  3569 00003FF5 E869010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3570                              <1> 		; esi = physical address of [u.namep]
  3571                              <1> 		; ecx = byte count in the page
  3572 00003FFA 803E2F              <1> 	cmp	byte [esi], '/'
  3573                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3574 00003FFD 751D                <1> 	jne	short namei_1
  3575                              <1> 		; bne 1f
  3576 00003FFF FF05[18650000]      <1> 	inc	dword [u.namep]
  3577                              <1> 		; inc u.namep / go to next char
  3578                              <1> 	; 03/02/2022
  3579 00004005 49                  <1> 	dec	ecx
  3580                              <1> 	;dec	cx ; remain byte count in the page
  3581 00004006 7506                <1> 	jnz	short namei_0
  3582                              <1> 	; 12/10/2015
  3583 00004008 E856010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3584                              <1> 		; esi = physical address (page start + offset)
  3585                              <1> 		; ecx = byte count in the page
  3586 0000400D 4E                  <1> 	dec	esi
  3587                              <1> namei_0:
  3588 0000400E 46                  <1> 	inc 	esi  ; go to next char
  3589 0000400F 66A1[EE640000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3590                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3591 00004015 C605[E4640000]00    <1> 	mov	byte [cdev], 0
  3592                              <1> 		; clr cdev / clear device number
  3593                              <1> namei_1: ; 1:
  3594 0000401C F606FF              <1> 	test	byte [esi], 0FFh
  3595                              <1> namei_10: ; 03/02/2022 (jump from namei_8)
  3596 0000401F 74BF                <1> 	jz	short getf4
  3597                              <1> 	;jz	nig
  3598                              <1> 		; tstb *u.namep / is the character in file name a nul
  3599                              <1> 		; beq nig / yes, end of file name reached; 
  3600                              <1> 			; / branch to "nig"
  3601                              <1> namei_2: ; 1:
  3602                              <1> 	; 18/10/2015
  3603 00004021 8935[70650000]      <1> 	mov 	[nbase], esi
  3604 00004027 66890D[74650000]    <1> 	mov 	[ncount], cx
  3605                              <1> 	;
  3606                              <1> 	;mov	dx, 2
  3607 0000402E B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3608 00004030 E895080000          <1> 	call	access
  3609                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3610                              <1> 	; 'access' will not return here if user has not "r" permission !
  3611                              <1> 	; 03/02/2022
  3612 00004035 F605[F5610000]40    <1> 	test	byte [i.flgs+1], 40h
  3613                              <1> 	;test 	word [i.flgs], 4000h
  3614                              <1> 		; bit $40000,i.flgs / directory i-node?
  3615 0000403C 746A                <1>         jz      short namei_err
  3616                              <1> 		; beq error3 / no, got an error
  3617                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3618 0000403E 31C0                <1> 	xor	eax, eax
  3619 00004040 A3[1C650000]        <1> 	mov	[u.off], eax ; 0
  3620 00004045 66A1[F8610000]      <1> 	mov	ax, [i.size]
  3621 0000404B A3[14650000]        <1> 	mov	[u.dirp], eax
  3622                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3623                              <1> 		; clr u.off / u.off is file offset used by user
  3624 00004050 C705[10650000]-     <1> 	mov	dword [u.fofp], u.off
  3624 00004056 [1C650000]          <1>
  3625                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3626                              <1> 				  ; / the offset portion of fsp entry
  3627                              <1> namei_3: ; 2:
  3628 0000405A C705[20650000]-     <1> 	mov	dword [u.base], u.dirbuf
  3628 00004060 [32650000]          <1>
  3629                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3630                              <1> 				    ; / copied from a directory
  3631 00004064 C705[24650000]0A00- <1> 	mov 	dword [u.count], 10 	
  3631 0000406C 0000                <1>
  3632                              <1>  		; mov $10.,u.count / u.count is byte count 
  3633                              <1> 				 ; / for reads and writes
  3634 0000406E 66A1[E0640000]      <1> 	mov 	ax, [ii]
  3635                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3636 00004074 FE05[61650000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3637 0000407A E84B090000          <1>     	call	readi
  3638                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3639                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3640 0000407F 8B0D[28650000]      <1> 	mov 	ecx, [u.nread]
  3641 00004085 09C9                <1> 	or 	ecx, ecx
  3642                              <1> 		; tst u.nread
  3643 00004087 741B                <1> 	jz	short nib
  3644                              <1> 		; ble nib / gives error return
  3645                              <1> 	;
  3646 00004089 668B1D[32650000]    <1> 	mov 	bx, [u.dirbuf]
  3647 00004090 6621DB              <1> 	and 	bx, bx       
  3648                              <1> 		; tst u.dirbuf /
  3649 00004093 7522                <1> 	jnz	short namei_4
  3650                              <1> 		; bne 3f / branch when active directory entry 
  3651                              <1> 		       ; / (i-node word in entry non zero)
  3652 00004095 A1[1C650000]        <1> 	mov	eax, [u.off]
  3653 0000409A 83E80A              <1> 	sub	eax, 10
  3654 0000409D A3[14650000]        <1> 	mov	[u.dirp], eax
  3655                              <1> 		; mov u.off,u.dirp
  3656                              <1> 		; sub $10.,u.dirp
  3657 000040A2 EBB6                <1> 	jmp	short namei_3
  3658                              <1> 		; br 2b
  3659                              <1> 
  3660                              <1> 	; 18/07/2013
  3661                              <1> nib: 
  3662 000040A4 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3663 000040A6 F9                  <1> 	stc
  3664                              <1> nig:
  3665 000040A7 C3                  <1> 	retn
  3666                              <1> 
  3667                              <1> namei_err:
  3668                              <1> 	; 16/06/2015
  3669 000040A8 C705[4F650000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3669 000040B0 0000                <1>
  3670 000040B2 E92AF0FFFF          <1> 	jmp	error
  3671                              <1> 
  3672                              <1> namei_4: ; 3:
  3673                              <1> 	; 18/10/2015
  3674                              <1> 	; 12/10/2015
  3675                              <1> 	; 21/08/2015
  3676                              <1> 	; 18/07/2015
  3677 000040B7 8B2D[18650000]      <1> 	mov	ebp, [u.namep]
  3678                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3679 000040BD BF[34650000]        <1> 	mov 	edi, u.dirbuf + 2
  3680                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3681                              <1> 	; 18/10/2015
  3682 000040C2 8B35[70650000]      <1> 	mov	esi, [nbase]	
  3683 000040C8 668B0D[74650000]    <1> 	mov	cx, [ncount]
  3684                              <1> 	;
  3685 000040CF 6621C9              <1> 	and	cx, cx
  3686 000040D2 7505                <1> 	jnz	short namei_5	
  3687                              <1> 	;
  3688 000040D4 E890000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3689                              <1> 		; esi = physical address (page start + offset)
  3690                              <1> 		; ecx = byte count in the page
  3691                              <1> namei_5: ; 3:
  3692 000040D9 45                  <1> 	inc	ebp ; 18/07/2015
  3693 000040DA AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3694                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3695 000040DB 08C0                <1> 	or 	al, al
  3696 000040DD 741C                <1> 	jz 	short namei_7
  3697                              <1> 		; beq 3f / if char is nul, then the last char in string
  3698                              <1> 			; / has been moved
  3699 000040DF 3C2F                <1> 	cmp	al, '/'
  3700                              <1> 		; cmp r4,$'/ / is char a </>
  3701 000040E1 7418                <1> 	je 	short namei_7
  3702                              <1> 		; beq 3f
  3703                              <1> 	; 03/02/2022
  3704 000040E3 49                  <1> 	dec	ecx	
  3705                              <1> 	; 12/10/2015
  3706                              <1> 	;dec	cx ; remain byte count in the page
  3707 000040E4 7505                <1> 	jnz	short namei_6
  3708 000040E6 E87E000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3709                              <1> 		; esi = physical address (page start + offset)
  3710                              <1> 		; ecx = byte count in the page
  3711                              <1> namei_6:
  3712 000040EB 81FF[3C650000]      <1>         cmp     edi, u.dirbuf + 10
  3713                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3714                              <1> 				     ; / all 8 bytes of file name
  3715 000040F1 74E6                <1> 	je	short namei_5
  3716                              <1> 		; beq 3b
  3717 000040F3 AE                  <1> 	scasb	
  3718                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3719                              <1> 			      ; / char read from directory
  3720 000040F4 74E3                <1> 	je 	short namei_5
  3721                              <1> 		; beq 3b / branch if chars match
  3722                              <1> namei_9:
  3723 000040F6 E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3724                              <1> 		; br 2b / file names do not match go to next directory entry
  3725                              <1> namei_7: ; 3:
  3726 000040FB 81FF[3C650000]      <1> 	cmp	edi, u.dirbuf + 10
  3727                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3728 00004101 7406                <1> 	je	short namei_8
  3729                              <1> 		; beq 3f
  3730 00004103 8A27                <1> 	mov 	ah, [edi]
  3731                              <1> 	;inc 	edi 
  3732 00004105 20E4                <1> 	and 	ah, ah
  3733                              <1> 		; tstb (r3)+ /
  3734                              <1>         ;jnz	namei_3
  3735                              <1> 		; bne 2b
  3736                              <1> 	; 03/02/2020
  3737 00004107 75ED                <1> 	jnz	short namei_9
  3738                              <1> namei_8: ; 3
  3739 00004109 892D[18650000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3740                              <1> 		; mov r2,u.namep / u.namep points to char 
  3741                              <1> 			       ; / following a / or nul
  3742                              <1> 	;mov	bx, [u.dirbuf]
  3743                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3744                              <1> 				; / entry to r1
  3745                              <1> 	;;;;
  3746                              <1> 	; 14/05/2022 - Retro UNIX (8086/386) feature only !
  3747                              <1> 	; ! 'pwd' utility modification !
  3748                              <1> 	; ((if directory entry name is a dotdot)))
  3749                              <1> 	;; check if it is mounted device's root directory inode
  3750                              <1> 	; and if so, replace it with parent dir inode number
  3751                              <1> 	;  of mounting directory in [mntp].
  3752                              <1> 
  3753 0000410F 668B1D[32650000]    <1> 	mov	bx, [u.dirbuf]
  3754                              <1> 
  3755 00004116 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3756 0000411A 753C                <1> 	jne	short namei_11
  3757                              <1> 
  3758 0000411C 663B1D[E0640000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3759 00004123 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3760                              <1> 
  3761                              <1> 	;cmp	[idev], bh ; 0
  3762 00004125 383D[E4640000]      <1> 	cmp	[cdev], bh ; 0
  3763                              <1> 			; 0 = root fs, dev num in [rdev]
  3764                              <1> 			; 1 = mounted, dev num in [mdev]
  3765 0000412B 762B                <1> 	jna	short namei_11
  3766                              <1> 
  3767                              <1> 	; dotdot (parent directory link) check
  3768 0000412D 66813D[34650000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3768 00004135 2E                  <1>
  3769 00004136 7520                <1> 	jne	short namei_11
  3770 00004138 803D[36650000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3771 0000413F 7517                <1> 	jne	short namei_11
  3772                              <1> 	
  3773                              <1> 	; (This may not be necessary because [idev] = 1
  3774                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3775 00004141 66391D[E8640000]    <1> 	cmp	[mnti], bx ; 41
  3776 00004148 760E                <1> 	jna	short namei_11
  3777                              <1> 	
  3778                              <1> 	; change inumber to parent dir inum of mount directory
  3779 0000414A 668B1D[EA640000]    <1> 	mov	bx, [mntp]
  3780 00004151 C605[E4640000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3781                              <1> namei_11:
  3782                              <1> 	;;;;
  3783                              <1> 
  3784 00004158 20C0                <1> 	and 	al, al
  3785                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3786                              <1> 		      ;  / if r4 = </> then go to next directory
  3787                              <1> 	; 15/05/2022
  3788 0000415A 6689D8              <1> 	mov	ax, bx
  3789                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3790                              <1>   	; 03/02/2022
  3791 0000415D E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3792                              <1> 	;jnz	namei_2 
  3793                              <1> 		; bne 1b
  3794                              <1> 	; AX = i-number of the file
  3795                              <1> ;;nig:
  3796 00004162 C3                  <1> 	retn
  3797                              <1> 		; tst (r0)+ / gives non-error return
  3798                              <1> ;;nib:
  3799                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3800                              <1> 		       ; ax = 0 -> file not found 
  3801                              <1> ;;	stc	; 27/05/2013
  3802                              <1> ;;	retn
  3803                              <1> 		; rts r0
  3804                              <1> 
  3805                              <1> trans_addr_nmbp:
  3806                              <1> 	; 03/02/2022
  3807                              <1> 	; 18/10/2015
  3808                              <1> 	; 12/10/2015
  3809 00004163 8B2D[18650000]      <1> 	mov 	ebp, [u.namep]
  3810                              <1> trans_addr_nm:
  3811                              <1> 	; 03/02/2022
  3812                              <1> 	; Convert virtual (pathname) address to physical address
  3813                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3814                              <1> 	; 18/10/2015
  3815                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3816                              <1> 	; 02/07/2015
  3817                              <1> 	; 17/06/2015
  3818                              <1> 	; 16/06/2015
  3819                              <1> 	;
  3820                              <1> 	; INPUTS: 
  3821                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3822                              <1> 	;	[u.pgdir] = user's page directory
  3823                              <1> 	; OUTPUT:
  3824                              <1> 	;       esi = physical address of the pathname
  3825                              <1> 	;	ecx = remain byte count in the page
  3826                              <1> 	;
  3827                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3828                              <1> 	;
  3829                              <1> 
  3830                              <1> 	; 03/02/2022
  3831 00004169 29C9                <1> 	sub	ecx, ecx
  3832                              <1> 
  3833 0000416B 833D[57650000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3834 00004172 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3835                              <1> 				     ; it is already physical address
  3836 00004174 50                  <1>    	push	eax	
  3837 00004175 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3838 00004177 E84DE6FFFF          <1>        	call	get_physical_addr ; get physical address
  3839 0000417C 7204                <1> 	jc	short tr_addr_nm_err
  3840                              <1> 	; 18/10/2015
  3841                              <1> 	; eax = physical address 
  3842                              <1> 	; cx = remain byte count in page (1-4096) 
  3843                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3844 0000417E 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3845 00004180 58                  <1> 	pop	eax 
  3846 00004181 C3                  <1> 	retn
  3847                              <1> 
  3848                              <1> tr_addr_nm_err:
  3849 00004182 A3[4F650000]        <1> 	mov	[u.error], eax
  3850                              <1> 	;pop 	eax
  3851 00004187 E955EFFFFF          <1> 	jmp	error
  3852                              <1> 
  3853                              <1> trans_addr_nmk:
  3854                              <1> 	; 12/10/2015
  3855                              <1> 	; 02/07/2015
  3856 0000418C 8B35[18650000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3857                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3858                              <1> 	; 03/02/2022
  3859 00004192 B510                <1> 	mov	ch, PAGE_SIZE/256
  3860 00004194 C3                  <1> 	retn
  3861                              <1> 
  3862                              <1> syschdir:
  3863                              <1> 	; 03/02/2022
  3864                              <1> 	; / makes the directory specified in the argument
  3865                              <1> 	; / the current directory
  3866                              <1> 	;
  3867                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3868                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3869                              <1> 	;
  3870                              <1> 	; 'syschdir' makes the directory specified in its argument
  3871                              <1> 	; the current working directory.
  3872                              <1> 	;
  3873                              <1> 	; Calling sequence:
  3874                              <1> 	;	syschdir; name
  3875                              <1> 	; Arguments:
  3876                              <1> 	;	name - address of the path name of a directory
  3877                              <1> 	;	       terminated by nul byte.	
  3878                              <1> 	; Inputs: -
  3879                              <1> 	; Outputs: -
  3880                              <1> 	; ...............................................................
  3881                              <1> 	;				
  3882                              <1> 	; Retro UNIX 8086 v1 modification:
  3883                              <1> 	;	 The user/application program puts address of 
  3884                              <1> 	;	 the path name in BX register as 'syschdir' 
  3885                              <1> 	; 	 system call argument.
  3886                              <1> 
  3887 00004195 891D[18650000]      <1> 	mov	[u.namep], ebx
  3888                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  3889 0000419B E841FEFFFF          <1> 	call	namei
  3890                              <1> 		; jsr r0,namei / find its i-number
  3891                              <1> 	;jc	error
  3892                              <1> 		; br error3
  3893 000041A0 730F                <1> 	jnc	short syschdir0
  3894                              <1> 	; 'directory not found !' error
  3895 000041A2 C705[4F650000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3895 000041AA 0000                <1>
  3896 000041AC E930EFFFFF          <1> 	jmp	error
  3897                              <1> syschdir0:
  3898                              <1> 	; 03/02/2022
  3899 000041B1 B202                <1> 	mov	dl, 2  ; read access ; 03/02/2022 (BugFix)
  3900 000041B3 E812070000          <1> 	call	access
  3901                              <1> 		; jsr r0,access; 2 / get i-node into core
  3902                              <1> 	; 03/02/2022
  3903 000041B8 F605[F5610000]40    <1> 	test	byte [i.flgs+1], 40h
  3904                              <1> 	;test	word [i.flgs], 4000h
  3905                              <1> 		; bit $40000,i.flgs / is it a directory?
  3906                              <1> 	;jz	error 
  3907                              <1> 		; beq error3 / no error
  3908 000041BF 750F                <1> 	jnz	short syschdir1
  3909 000041C1 C705[4F650000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3909 000041C9 0000                <1>
  3910 000041CB E911EFFFFF          <1> 	jmp	error
  3911                              <1> syschdir1:
  3912 000041D0 66A3[04650000]      <1> 	mov	[u.cdir], ax
  3913                              <1> 		; mov r1,u.cdir / move i-number to users 
  3914                              <1> 			      ; / current directory
  3915 000041D6 66A1[E4640000]      <1> 	mov	ax, [cdev]
  3916 000041DC 66A3[44650000]      <1> 	mov	[u.cdrv], ax
  3917                              <1> 		; mov cdev,u.cdev / move its device to users 
  3918                              <1> 			        ; / current device
  3919 000041E2 E91AEFFFFF          <1> 	jmp	sysret
  3920                              <1> 		; br sysret3
  3921                              <1> 	
  3922                              <1> syschmod: ; < change mode of file >
  3923                              <1> 	; 29/04/2022 (bugfix)
  3924                              <1> 	; 03/02/2022
  3925                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3926                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3927                              <1> 	;
  3928                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3929                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3930                              <1> 	; changed to 'mode'.
  3931                              <1> 	;
  3932                              <1> 	; Calling sequence:
  3933                              <1> 	;	syschmod; name; mode
  3934                              <1> 	; Arguments:
  3935                              <1> 	;	name - address of the file name
  3936                              <1> 	;	       terminated by null byte.
  3937                              <1> 	;	mode - (new) mode/flags < attributes >
  3938                              <1> 	;	
  3939                              <1> 	; Inputs: -
  3940                              <1> 	; Outputs: -
  3941                              <1> 	; ...............................................................
  3942                              <1> 	;				
  3943                              <1> 	; Retro UNIX 8086 v1 modification: 
  3944                              <1> 	;       'syschmod' system call has two arguments; so,
  3945                              <1> 	;	* 1st argument, name is pointed to by BX register
  3946                              <1> 	;	* 2nd argument, mode is in CX register
  3947                              <1> 	;
  3948                              <1> 	; Mode bits (Flags):
  3949                              <1> 	;	bit 0 - write permission for non-owner (1)
  3950                              <1> 	;	bit 1 - read permission for non-owner (2)
  3951                              <1> 	;	bit 2 - write permission for owner (4)
  3952                              <1> 	;	bit 3 - read permission for owner (8)
  3953                              <1> 	;	bit 4 - executable flag (16) 	
  3954                              <1> 	;	bit 5 - set user ID on execution flag (32) 
  3955                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3956                              <1> 	;	bit 12 - large file flag (4096)
  3957                              <1> 	;	bit 13 - file has modified flag (always on) (8192)
  3958                              <1> 	;	bit 14 - directory flag (16384)
  3959                              <1> 	;	bit 15 - 'i-node is allocated' flag (32768)
  3960                              <1> 
  3961                              <1> 	; / name; mode
  3962 000041E7 E815000000          <1> 	call	isown
  3963                              <1> 		;jsr r0,isown / get the i-node and check user status
  3964                              <1> 	; 03/02/2022
  3965 000041EC F605[F5610000]40    <1> 	test	byte [i.flgs+1], 40h
  3966                              <1> 	;test	word [i.flgs], 4000h
  3967                              <1> 		; bit $40000,i.flgs / directory?
  3968 000041F3 7402                <1> 	jz	short syschmod1
  3969                              <1> 		; beq 2f / no
  3970                              <1> 	; AL = (new) mode
  3971 000041F5 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3972                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3973                              <1> 			   ; / executable modes
  3974                              <1> syschmod1: ; 2:
  3975 000041F7 A2[F4610000]        <1> 	mov	[i.flgs], al	
  3976                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3977                              <1> 	;jmp	short isown1
  3978                              <1> 	;	; br 1f ; (jmp sysret4)
  3979                              <1> 	; 29/04/2022
  3980 000041FC E900EFFFFF          <1> 	jmp	sysret
  3981                              <1> 
  3982                              <1> isown:
  3983                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3984                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3985                              <1> 	;
  3986                              <1> 	; 'isown' is given a file name (the 1st argument).
  3987                              <1> 	;  It find the i-number of that file via 'namei' 
  3988                              <1> 	;  then gets the i-node into core via 'iget'.
  3989                              <1> 	;  It then tests to see if the user is super user. 
  3990                              <1> 	;  If not, it cheks to see if the user is owner of 
  3991                              <1> 	;  the file. If he is not an error occurs.
  3992                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3993                              <1> 	;  the inode has been modificed and the 2nd argument of
  3994                              <1> 	;  the call is put in r2.
  3995                              <1> 	;
  3996                              <1> 	; INPUTS ->
  3997                              <1> 	;    arguments of syschmod and syschown calls
  3998                              <1> 	; OUTPUTS ->
  3999                              <1> 	;    u.uid - id of user
  4000                              <1> 	;    imod - set to a 1
  4001                              <1> 	;    r2 - contains second argument of the system call				 	
  4002                              <1> 	;
  4003                              <1> 	;   ((AX=R2) output as 2nd argument)
  4004                              <1> 	;
  4005                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4006                              <1> 	;
  4007                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4008                              <1> 	;; ! 2nd argument on top of stack !
  4009                              <1> 	;; 22/06/2015 - 32 bit modifications
  4010                              <1> 	;; 07/07/2013
  4011 00004201 891D[18650000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4012 00004207 51                  <1> 	push 	ecx ;; 2nd argument
  4013                              <1> 	;;
  4014 00004208 E8D4FDFFFF          <1> 	call	namei
  4015                              <1> 		; jsr r0,namei / get its i-number
  4016                              <1>        ; Retro UNIX 8086 v1 modification !
  4017                              <1>        ; ax = 0 -> file not found 
  4018                              <1> 	;and	ax, ax
  4019                              <1> 	;jz	error
  4020                              <1> 	;jc	error ; 27/05/2013
  4021                              <1> 		; br error3
  4022 0000420D 730F                <1> 	jnc	short isown0
  4023                              <1> 	; 'file not found !' error
  4024 0000420F C705[4F650000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4024 00004217 0000                <1>
  4025 00004219 E9C3EEFFFF          <1> 	jmp	error
  4026                              <1> isown0:
  4027 0000421E E8D3050000          <1> 	call	iget
  4028                              <1> 		; jsr r0,iget / get i-node into core
  4029 00004223 A0[46650000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4030 00004228 08C0                <1> 	or	al, al
  4031                              <1> 		; tstb u.uid / super user?
  4032 0000422A 7417                <1> 	jz	short isown1
  4033                              <1> 		; beq 1f / yes, branch
  4034 0000422C 3A05[F7610000]      <1> 	cmp	al, [i.uid]
  4035                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4036                              <1> 				 ; / the file
  4037                              <1> 	;jne	error
  4038                              <1> 		; beq 1f / yes
  4039                              <1> 		; jmp error3 / no, error
  4040 00004232 740F                <1> 	je	short isown1
  4041                              <1> 
  4042 00004234 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4042 0000423C 0000                <1>
  4043                              <1> 			;  'permission denied !' error
  4044 0000423E E99EEEFFFF          <1> 	jmp	error
  4045                              <1> isown1: ; 1:
  4046 00004243 E8B8060000          <1> 	call	setimod
  4047                              <1> 		; jsr r0,setimod / indicates 
  4048                              <1> 		;	       ; / i-node has been modified
  4049 00004248 58                  <1> 	pop	eax ; 2nd argument
  4050                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4051                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4052 00004249 C3                  <1> 	retn
  4053                              <1> 		; rts r0
  4054                              <1> 
  4055                              <1> ;;arg:  ; < get system call arguments >
  4056                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4057                              <1> 	; of form:
  4058                              <1> 	;	sys 'routine' ; arg1
  4059                              <1> 	;		or
  4060                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4061                              <1> 	;		or
  4062                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4063                              <1> 	;	
  4064                              <1> 	; INPUTS ->
  4065                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4066                              <1> 	;	This pointers's value is actually the value of
  4067                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4068                              <1> 	;	made to process the sys instruction
  4069                              <1> 	;    r0 - contains the return address for the routine
  4070                              <1> 	;	that called arg. The data in the word pointer 
  4071                              <1> 	;	to by the return address is used as address
  4072                              <1> 	;	in which the extracted argument is stored   		
  4073                              <1> 	;    	
  4074                              <1> 	; OUTPUTS ->
  4075                              <1> 	;    'address' - contains the extracted argument 
  4076                              <1> 	;    u.sp+18 - is incremented by 2 
  4077                              <1> 	;    r1 - contains the extracted argument
  4078                              <1> 	;    r0 - points to the next instruction to be
  4079                              <1> 	;	 executed in the calling routine.
  4080                              <1> 	;
  4081                              <1>   
  4082                              <1> 	; mov u.sp,r1
  4083                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4084                              <1> 			; / into argument of arg2
  4085                              <1> 	; add $2,18.(r1) / point pc on stack 
  4086                              <1> 			      ; / to next system argument
  4087                              <1> 	; rts r0
  4088                              <1> 
  4089                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4090                              <1> 	; 'arg2' takes first argument in system call
  4091                              <1> 	;  (pointer to name of the file) and puts it in location
  4092                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4093                              <1> 	;  and on top of the stack
  4094                              <1> 	;	
  4095                              <1> 	; INPUTS ->
  4096                              <1> 	;    u.sp, r0
  4097                              <1> 	;    	
  4098                              <1> 	; OUTPUTS ->
  4099                              <1> 	;    u.namep
  4100                              <1> 	;    u.off 
  4101                              <1> 	;    u.off pushed on stack
  4102                              <1> 	;    r1
  4103                              <1> 	;
  4104                              <1> 
  4105                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4106                              <1> 				; / first arg in sys call
  4107                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4108                              <1> 				; / second arg in sys call
  4109                              <1> 	; mov r0,r1 / r0 points to calling routine
  4110                              <1> 	; mov (sp),r0 / put operation code back in r0
  4111                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4112                              <1> 			; / on stack
  4113                              <1> 	; jmp (r1) / return to calling routine
  4114                              <1> 
  4115                              <1> syschown: ; < change owner of file >
  4116                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4117                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4118                              <1> 	;
  4119                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4120                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4121                              <1> 	; changed to 'owner'
  4122                              <1> 	;
  4123                              <1> 	; Calling sequence:
  4124                              <1> 	;	syschown; name; owner
  4125                              <1> 	; Arguments:
  4126                              <1> 	;	name - address of the file name
  4127                              <1> 	;	       terminated by null byte.
  4128                              <1> 	;	owner - (new) owner (number/ID)
  4129                              <1> 	;	
  4130                              <1> 	; Inputs: -
  4131                              <1> 	; Outputs: -
  4132                              <1> 	; ...............................................................
  4133                              <1> 	;				
  4134                              <1> 	; Retro UNIX 8086 v1 modification: 
  4135                              <1> 	;       'syschown' system call has two arguments; so,
  4136                              <1> 	;	* 1st argument, name is pointed to by BX register
  4137                              <1> 	;	* 2nd argument, owner number is in CX register
  4138                              <1> 	;
  4139                              <1> 	; / name; owner
  4140 0000424A E8B2FFFFFF          <1> 	call	isown
  4141                              <1> 		; jsr r0,isown / get the i-node and check user status
  4142 0000424F 803D[46650000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4143                              <1> 		; tstb u.uid / super user
  4144 00004256 7418                <1> 	jz	short syschown1
  4145                              <1> 		; beq 2f / yes, 2f
  4146 00004258 F605[F4610000]20    <1>         test    byte [i.flgs], 20h ; 32
  4147                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4148                              <1> 	;jnz	error
  4149                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4150 0000425F 740F                <1> 	jz	short syschown1
  4151                              <1> 	; 'permission denied !'
  4152 00004261 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4152 00004269 0000                <1>
  4153 0000426B E971EEFFFF          <1> 	jmp	error
  4154                              <1> syschown1: ; 2:
  4155                              <1> 	; AL = owner (number/ID)
  4156 00004270 A2[F7610000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4157                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4158                              <1> 			       ; / in the i-node
  4159 00004275 E987EEFFFF          <1> 	jmp	sysret
  4160                              <1> 	; 1: 
  4161                              <1> 		; jmp sysret4
  4162                              <1> 	; 3:
  4163                              <1> 		; jmp	error
  4164                              <1> 
  4165                              <1> systime: ; / get time of year
  4166                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4167                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4168                              <1> 	;
  4169                              <1> 	; 20/06/2013
  4170                              <1> 	; 'systime' gets the time of the year.
  4171                              <1> 	; The present time is put on the stack.
  4172                              <1> 	;
  4173                              <1> 	; Calling sequence:
  4174                              <1> 	;	systime
  4175                              <1> 	; Arguments: -
  4176                              <1> 	;	
  4177                              <1> 	; Inputs: -
  4178                              <1> 	; Outputs: sp+2, sp+4 - present time
  4179                              <1> 	; ...............................................................
  4180                              <1> 	;	
  4181                              <1> 	; Retro UNIX 8086 v1 modification: 
  4182                              <1> 	;       'systime' system call will return to the user
  4183                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4184                              <1> 	;
  4185                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4186                              <1> 	;	system call for PC compatibility !!		 	
  4187                              <1> 
  4188 0000427A E8B3E9FFFF          <1> 	call 	epoch
  4189 0000427F A3[00650000]        <1> 	mov 	[u.r0], eax
  4190                              <1> 		; mov s.time,4(sp)
  4191                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4192                              <1> 				   ; / on the stack
  4193                              <1> 		; br sysret4
  4194 00004284 E978EEFFFF          <1> 	jmp	sysret 
  4195                              <1> 
  4196                              <1> sysstime: ; / set time
  4197                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4198                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4199                              <1> 	;
  4200                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4201                              <1> 	;
  4202                              <1> 	; Calling sequence:
  4203                              <1> 	;	sysstime
  4204                              <1> 	; Arguments: -
  4205                              <1> 	;	
  4206                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4207                              <1> 	; Outputs: -
  4208                              <1> 	; ...............................................................
  4209                              <1> 	;	
  4210                              <1> 	; Retro UNIX 8086 v1 modification: 
  4211                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4212                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4213                              <1> 	; 
  4214                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4215                              <1> 	;	to get sysstime system call arguments from the user;
  4216                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4217                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4218                              <1> 	;
  4219                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4220                              <1> 	;	system call for PC compatibility !!	
  4221                              <1> 
  4222 00004289 803D[46650000]00    <1> 	cmp	byte [u.uid], 0
  4223                              <1> 		; tstb u.uid / is user the super user
  4224                              <1> 	;ja	error
  4225                              <1> 		; bne error4 / no, error
  4226 00004290 760F                <1> 	jna	short systime1
  4227                              <1> 	; 'permission denied !'
  4228 00004292 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4228 0000429A 0000                <1>
  4229 0000429C E940EEFFFF          <1> 	jmp	error
  4230                              <1> systime1:
  4231                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4232                              <1> 	; EBX = unix (epoch) time (from user)
  4233 000042A1 89D8                <1> 	mov	eax, ebx
  4234 000042A3 E807EBFFFF          <1> 	call 	set_date_time
  4235                              <1> 		; mov 4(sp),s.time
  4236                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4237 000042A8 E954EEFFFF          <1> 	jmp	sysret
  4238                              <1> 		; br sysret4
  4239                              <1> 
  4240                              <1> sysbreak:
  4241                              <1> 	; 18/10/2015
  4242                              <1> 	; 07/10/2015
  4243                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4244                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4245                              <1> 	;
  4246                              <1> 	; 'sysbreak' sets the programs break points. 
  4247                              <1> 	; It checks the current break point (u.break) to see if it is
  4248                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4249                              <1> 	; even address (if it was odd) and the area between u.break
  4250                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4251                              <1> 	; in u.break and control is passed to 'sysret'.
  4252                              <1> 	;
  4253                              <1> 	; Calling sequence:
  4254                              <1> 	;	sysbreak; addr
  4255                              <1> 	; Arguments: -
  4256                              <1> 	;	
  4257                              <1> 	; Inputs: u.break - current breakpoint
  4258                              <1> 	; Outputs: u.break - new breakpoint 
  4259                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4260                              <1> 	; ...............................................................
  4261                              <1> 	;	
  4262                              <1> 	; Retro UNIX 8086 v1 modification:
  4263                              <1> 	;	The user/application program puts breakpoint address
  4264                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4265                              <1> 	; 	(argument transfer method 1)
  4266                              <1> 	;
  4267                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4268                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4269                              <1> 	;  NOTE:
  4270                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4271                              <1> 	;	'u.break' address) of user's memory for original unix's
  4272                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4273                              <1> 
  4274                              <1> 		; mov u.break,r1 / move users break point to r1
  4275                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4276                              <1> 		; blos 1f / yes, 1f
  4277                              <1> 	; 23/06/2015
  4278 000042AD 8B2D[2C650000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4279                              <1> 	;and	ebp, ebp
  4280                              <1> 	;jz	short sysbreak_3 
  4281                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4282                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4283 000042B3 8B15[F8640000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4284 000042B9 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4285                              <1> 	; 07/10/2015
  4286 000042BC 891D[2C650000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4287                              <1> 	;
  4288 000042C2 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4289                              <1> 			   ; with top of user's stack (virtual!)
  4290 000042C4 7327                <1> 	jnb	short sysbreak_3
  4291                              <1> 		; cmp r1,sp / is it the same or higher 
  4292                              <1> 			  ; / than the stack?
  4293                              <1> 		; bhis 1f / yes, 1f
  4294 000042C6 89DE                <1> 	mov	esi, ebx
  4295 000042C8 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4296 000042CA 7621                <1> 	jna	short sysbreak_3 
  4297                              <1> 	;push	ebx
  4298                              <1> sysbreak_1:
  4299 000042CC 89EB                <1> 	mov	ebx, ebp  
  4300 000042CE E8F6E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4301 000042D3 0F82A9FEFFFF        <1> 	jc	tr_addr_nm_err
  4302                              <1> 	; 18/10/2015
  4303 000042D9 89C7                <1> 	mov	edi, eax 
  4304 000042DB 29C0                <1> 	sub	eax, eax ; 0
  4305                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4306 000042DD 39CE                <1> 	cmp	esi, ecx
  4307 000042DF 7302                <1> 	jnb	short sysbreak_2
  4308 000042E1 89F1                <1> 	mov	ecx, esi
  4309                              <1> sysbreak_2:
  4310 000042E3 29CE                <1> 	sub	esi, ecx
  4311 000042E5 01CD                <1> 	add	ebp, ecx
  4312 000042E7 F3AA                <1> 	rep 	stosb
  4313 000042E9 09F6                <1> 	or	esi, esi
  4314 000042EB 75DF                <1> 	jnz	short sysbreak_1
  4315                              <1> 	;
  4316                              <1> 		; bit $1,r1 / is it an odd address
  4317                              <1> 		; beq 2f / no, its even
  4318                              <1> 		; clrb (r1)+ / yes, make it even
  4319                              <1> 	; 2: / clear area between the break point and the stack
  4320                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4321                              <1> 		; bhis 1f / yes, quit
  4322                              <1> 		; clr (r1)+ / clear word
  4323                              <1> 		; br 2b / go back
  4324                              <1> 	;pop	ebx
  4325                              <1> sysbreak_3: ; 1:
  4326                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4327                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4328                              <1> 			; / in u.break (set new break point)
  4329                              <1> 		; br sysret4 / br sysret
  4330 000042ED E90FEEFFFF          <1> 	jmp	sysret
  4331                              <1> 
  4332                              <1> maknod: 
  4333                              <1> 	; 12/02/2022
  4334                              <1> 	; 03/02/2022
  4335                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4336                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4337                              <1> 	;
  4338                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4339                              <1> 	; for this i-node in the current directory.
  4340                              <1> 	;
  4341                              <1> 	; INPUTS ->
  4342                              <1> 	;    r1 - contains mode
  4343                              <1> 	;    ii - current directory's i-number	
  4344                              <1> 	;    	
  4345                              <1> 	; OUTPUTS ->
  4346                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4347                              <1> 	;    i.flgs - flags in new i-node 
  4348                              <1> 	;    i.uid - filled with u.uid
  4349                              <1> 	;    i.nlks - 1 is put in the number of links
  4350                              <1> 	;    i.ctim - creation time				
  4351                              <1> 	;    i.ctim+2 - modification time
  4352                              <1> 	;    imod - set via call to setimod
  4353                              <1> 	;	
  4354                              <1> 	; ((AX = R1)) input
  4355                              <1> 	;
  4356                              <1> 	; (Retro UNIX Prototype : 
  4357                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4358                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4359                              <1> 
  4360                              <1> 	; / r1 contains the mode
  4361 000042F2 80CC80              <1> 	or 	ah, 80h ; 10000000b
  4362                              <1> 		; bis $100000,r1 / allocate flag set
  4363 000042F5 6650                <1> 	push	ax ; *
  4364                              <1> 		; mov r1,-(sp) / put mode on stack
  4365                              <1> 	; 31/07/2013
  4366 000042F7 66A1[E0640000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4367                              <1> 		; mov ii,r1 / move current i-number to r1
  4368 000042FD B201                <1> 	mov	dl, 1 ; owner flag mask
  4369 000042FF E8C6050000          <1> 	call	access	
  4370                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4371                              <1> 	; 03/02/2022
  4372 00004304 50                  <1> 	push	eax ; **
  4373                              <1> 	;push	ax
  4374                              <1> 		; mov r1,-(sp) / put i-number on stack
  4375 00004305 66B82800            <1> 	mov	ax, 40
  4376                              <1> 		; mov $40.,r1 / r1 = 40
  4377                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4378 00004309 6640                <1> 	inc	ax
  4379                              <1> 		; inc r1 / r1 = r1 + 1
  4380 0000430B E87F060000          <1> 	call	imap
  4381                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4382                              <1> 			    ; /	inode map in r2 & m
  4383                              <1>   
  4384                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4385                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4386                              <1> 
  4387                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4388                              <1> 	;	       Inode count must be checked here
  4389                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4390                              <1> 
  4391                              <1> 	; 12/02/2022 - Retro UNIX 386 v1.0 (Kernel v0.2.0.18)
  4392                              <1> 	; (inode count check)
  4393                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4394                              <1> 
  4395 00004310 730F                <1> 	jnc	short maknod2
  4396                              <1> 
  4397                              <1> 	; no free inode in inode table !
  4398 00004312 C705[4F650000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4398 0000431A 0000                <1>
  4399                              <1> 			; miscellaneous/other errors
  4400 0000431C E9C0EDFFFF          <1> 	jmp	error	
  4401                              <1> maknod2: 	
  4402 00004321 8413                <1> 	test	[ebx], dl
  4403                              <1> 		; bitb mq,(r2) / is the i-node active
  4404 00004323 75E4                <1> 	jnz	short maknod1
  4405                              <1> 		; bne 1b / yes, try the next one
  4406 00004325 0813                <1> 	or	[ebx], dl
  4407                              <1> 		; bisb mq,(r2) / no, make it active 
  4408                              <1> 			     ; / (put a 1 in the bit map)
  4409 00004327 E8CA040000          <1> 	call	iget
  4410                              <1> 		; jsr r0,iget / get i-node into core
  4411                              <1> 	; 03/02/2022
  4412 0000432C F605[F5610000]80    <1> 	test	byte [i.flgs+1], 80h
  4413                              <1> 	;test	word [i.flgs], 8000h 
  4414                              <1> 		; tst i.flgs / is i-node already allocated
  4415 00004333 75D4                <1> 	jnz	short maknod1	
  4416                              <1> 		; blt 1b / yes, look for another one
  4417 00004335 66A3[32650000]      <1> 	mov	[u.dirbuf], ax
  4418                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4419                              <1> 	; 03/02/2022
  4420 0000433B 58                  <1> 	pop	eax ; **
  4421                              <1> 	;pop	ax
  4422                              <1> 		; mov (sp)+,r1 / get current i-number back
  4423 0000433C E8B5040000          <1> 	call	iget
  4424                              <1> 		; jsr r0,iget / get i-node in core
  4425 00004341 E852F7FFFF          <1> 	call	mkdir
  4426                              <1> 		; jsr r0,mkdir / make a directory entry 
  4427                              <1> 			     ; / in current directory
  4428 00004346 66A1[32650000]      <1> 	mov	ax, [u.dirbuf]
  4429                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4430 0000434C E8A5040000          <1> 	call	iget
  4431                              <1> 		; jsr r0,iget / get it into core
  4432                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4433                              <1> 	;mov	ecx, 8
  4434                              <1> 	; 03/02/2022 
  4435 00004351 29C9                <1> 	sub	ecx, ecx
  4436 00004353 B108                <1> 	mov	cl, 8
  4437 00004355 31C0                <1> 	xor	eax, eax ; 0
  4438 00004357 BF[F4610000]        <1> 	mov	edi, inode 
  4439 0000435C F3AB                <1> 	rep	stosd
  4440                              <1> 	;
  4441 0000435E 668F05[F4610000]    <1> 	pop	word [i.flgs] ; *
  4442                              <1> 		; mov (sp)+,i.flgs / fill flags
  4443 00004365 8A0D[46650000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4444 0000436B 880D[F7610000]      <1> 	mov 	[i.uid], cl
  4445                              <1> 		; movb u.uid,i.uid / user id	
  4446 00004371 C605[F6610000]01    <1> 	mov     byte [i.nlks], 1
  4447                              <1> 		; movb $1,i.nlks / 1 link
  4448                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4449                              <1> 	;mov	eax, [s.time]
  4450                              <1> 	;mov 	[i.ctim], eax
  4451                              <1> 	 	; mov s.time,i.ctim / time created
  4452                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4453                              <1> 	; Retro UNIX 8086 v1 modification !
  4454                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4455                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4456                              <1> 	;call setimod
  4457                              <1> 		; jsr r0,setimod / set modified flag
  4458                              <1> 	;retn
  4459                              <1> 		; rts r0 / return
  4460                              <1> 	; 03/02/2022
  4461 00004378 E983050000          <1> 	jmp	setimod
  4462                              <1> 
  4463                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4464                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4465                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4466                              <1> 	;
  4467                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4468                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4469                              <1> 	; The file descriptor refers to a file open for reading or
  4470                              <1> 	; writing. The read (or write) pointer is set as follows:
  4471                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4472                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4473                              <1> 	;	  current location plus offset.
  4474                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4475                              <1> 	;	  size of file plus offset.
  4476                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4477                              <1> 	;
  4478                              <1> 	; Calling sequence:
  4479                              <1> 	;	sysseek; offset; ptrname
  4480                              <1> 	; Arguments:
  4481                              <1> 	;	offset - number of bytes desired to move 
  4482                              <1> 	;		 the r/w pointer
  4483                              <1> 	;	ptrname - a switch indicated above
  4484                              <1> 	;
  4485                              <1> 	; Inputs: r0 - file descriptor 
  4486                              <1> 	; Outputs: -
  4487                              <1> 	; ...............................................................
  4488                              <1> 	;	
  4489                              <1> 	; Retro UNIX 8086 v1 modification: 
  4490                              <1> 	;       'sysseek' system call has three arguments; so,
  4491                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4492                              <1> 	;	* 2nd argument, offset is in CX register
  4493                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4494                              <1> 	;	
  4495                              <1> 
  4496 0000437D E822000000          <1> 	call	seektell
  4497                              <1> 	; AX = u.count
  4498                              <1> 	; BX = *u.fofp
  4499                              <1> 		; jsr r0,seektell / get proper value in u.count
  4500                              <1> 		; add u.base,u.count / add u.base to it
  4501 00004382 0305[20650000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4502 00004388 8903                <1> 	mov	[ebx], eax
  4503                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4504 0000438A E972EDFFFF          <1> 	jmp	sysret
  4505                              <1> 		; br sysret4
  4506                              <1> 
  4507                              <1> systell: ; / get the r/w pointer
  4508                              <1> 	; 03/02/2022
  4509                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4510                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4511                              <1> 	;
  4512                              <1> 	; Retro UNIX 8086 v1 modification:
  4513                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4514                              <1> 	; 	    it returns with error !
  4515                              <1> 	; Inputs: r0 - file descriptor 
  4516                              <1> 	; Outputs: r0 - file r/w pointer
  4517                              <1> 
  4518                              <1> 	;xor	ecx, ecx ; 0
  4519                              <1> 	;mov	edx, 1 ; 05/08/2013
  4520                              <1> 	; 03/02/2022
  4521 0000438F 29D2                <1> 	sub	edx, edx
  4522 00004391 FEC2                <1> 	inc	dl
  4523                              <1> 	; edx = 1
  4524                              <1> 	;call 	seektell
  4525 00004393 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4526                              <1> 	;mov	ebx, [u.fofp]
  4527 00004398 8B03                <1> 	mov	eax, [ebx]
  4528 0000439A A3[00650000]        <1> 	mov	[u.r0], eax
  4529 0000439F E95DEDFFFF          <1> 	jmp	sysret
  4530                              <1> 
  4531                              <1> ; Original unix v1 'systell' system call:
  4532                              <1> 		; jsr r0,seektell
  4533                              <1> 		; br error4
  4534                              <1> 
  4535                              <1> seektell:
  4536                              <1> 	; 03/02/2022
  4537                              <1> 	; 03/01/2016
  4538                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4539                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4540                              <1> 	;
  4541                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4542                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4543                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4544                              <1> 	; getf. The i-node is brought into core and then u.count
  4545                              <1> 	; is checked to see it is a 0, 1, or 2.
  4546                              <1> 	; If it is 0 - u.count stays the same
  4547                              <1> 	;          1 - u.count = offset (u.fofp)
  4548                              <1> 	;	   2 - u.count = i.size (size of file)
  4549                              <1> 	; 	 		
  4550                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4551                              <1> 	;	Argument 1, file descriptor is in BX;
  4552                              <1> 	;	Argument 2, offset is in CX;
  4553                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4554                              <1> 	;
  4555                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4556                              <1> 	; call 	arg
  4557                              <1> 	;
  4558                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4559                              <1> 	;
  4560 000043A4 890D[20650000]      <1> 	mov 	[u.base], ecx ; offset
  4561                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4562                              <1> seektell0:
  4563 000043AA 8915[24650000]      <1> 	mov 	[u.count], edx
  4564                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4565                              <1> 	; mov	ax, bx
  4566                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4567                              <1> 			     ; / (index in u.fp list)
  4568                              <1> 	; call	getf
  4569                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4570                              <1> 	; BX = file descriptor (file number)
  4571 000043B0 E8F9FBFFFF          <1> 	call	getf1
  4572                              <1> 	; 03/02/2022
  4573 000043B5 09C0                <1> 	or	eax, eax
  4574                              <1> 	;or	ax, ax ; i-number of the file
  4575                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4576                              <1> 		             ; / put it on the stack
  4577                              <1> 	;jz	error
  4578                              <1> 		; beq error4 / if i-number is 0, not active so error
  4579 000043B7 750F                <1> 	jnz	short seektell1
  4580 000043B9 C705[4F650000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4580 000043C1 0000                <1>
  4581 000043C3 E919EDFFFF          <1> 	jmp	error
  4582                              <1> seektell1:
  4583                              <1> 	;push	eax
  4584 000043C8 80FC80              <1> 	cmp	ah, 80h
  4585 000043CB 7203                <1> 	jb	short seektell2
  4586                              <1> 		; bgt .+4 / if its positive jump
  4587 000043CD 66F7D8              <1> 	neg	ax
  4588                              <1> 		; neg r1 / if not make it positive
  4589                              <1> seektell2:
  4590 000043D0 E821040000          <1> 	call	iget
  4591                              <1> 		; jsr r0,iget / get its i-node into core
  4592 000043D5 8B1D[10650000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4593 000043DB 803D[24650000]01    <1> 	cmp	byte [u.count], 1
  4594                              <1> 		; cmp u.count,$1 / is ptr name =1
  4595 000043E2 7705                <1> 	ja	short seektell3
  4596                              <1> 		; blt 2f / no its zero
  4597 000043E4 740A                <1> 	je	short seektell_4
  4598                              <1> 		; beq 1f / yes its 1
  4599 000043E6 31C0                <1> 	xor	eax, eax
  4600                              <1> 	;jmp	short seektell_5
  4601 000043E8 C3                  <1> 	retn
  4602                              <1> seektell3:
  4603                              <1> 	; 03/01/2016
  4604                              <1> 	;movzx  eax, word [i.size]
  4605 000043E9 66A1[F8610000]      <1> 	mov	ax, [i.size]
  4606                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4607                              <1>                                    ; / in file in u.count
  4608                              <1> 	;jmp	short seektell_5
  4609                              <1> 		; br 2f
  4610 000043EF C3                  <1> 	retn
  4611                              <1> seektell_4: ; 1: / ptrname =1
  4612                              <1> 	;mov	ebx, [u.fofp]
  4613 000043F0 8B03                <1> 	mov	eax, [ebx]
  4614                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4615                              <1> ;seektell_5: ; 2: / ptrname =0
  4616                              <1> 	;mov	[u.count], eax
  4617                              <1> 	;pop	eax 
  4618                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4619 000043F2 C3                  <1> 	retn
  4620                              <1> 		; rts r0
  4621                              <1> 
  4622                              <1> sysintr: ; / set interrupt handling
  4623                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4624                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4625                              <1> 	;
  4626                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4627                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4628                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4629                              <1> 	; If one does the interrupt character in the tty buffer is
  4630                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4631                              <1> 	; 'sysret' is just called.	
  4632                              <1> 	;
  4633                              <1> 	; Calling sequence:
  4634                              <1> 	;	sysintr; arg
  4635                              <1> 	; Argument:
  4636                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4637                              <1> 	;	    - if 1, intterupts cause their normal result
  4638                              <1> 	;		 i.e force an exit.
  4639                              <1> 	;	    - if arg is a location within the program,
  4640                              <1> 	;		control is passed to that location when
  4641                              <1> 	;		an interrupt occurs.	
  4642                              <1> 	; Inputs: -
  4643                              <1> 	; Outputs: -
  4644                              <1> 	; ...............................................................
  4645                              <1> 	;	
  4646                              <1> 	; Retro UNIX 8086 v1 modification: 
  4647                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4648                              <1> 	;	then branches into sysquit.
  4649                              <1> 	;
  4650 000043F3 66891D[3E650000]    <1> 	mov	[u.intr], bx
  4651                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4652                              <1> 		; br 1f / go into quit routine
  4653 000043FA E902EDFFFF          <1> 	jmp	sysret
  4654                              <1> 
  4655                              <1> sysquit:
  4656                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4657                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4658                              <1> 	;
  4659                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4660                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4661                              <1> 	; tty exists. If one does the interrupt character in the tty
  4662                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4663                              <1> 	; 'sysret' is just called.	
  4664                              <1> 	;
  4665                              <1> 	; Calling sequence:
  4666                              <1> 	;	sysquit; arg
  4667                              <1> 	; Argument:
  4668                              <1> 	;	arg - if 0, this call diables quit signals from the
  4669                              <1> 	;		typewriter (ASCII FS)
  4670                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4671                              <1> 	;		cease and a core image to be produced.
  4672                              <1> 	;		 i.e force an exit.
  4673                              <1> 	;	    - if arg is an addres in the program,
  4674                              <1> 	;		a quit causes control to sent to that
  4675                              <1> 	;		location.	
  4676                              <1> 	; Inputs: -
  4677                              <1> 	; Outputs: -
  4678                              <1> 	; ...............................................................
  4679                              <1> 	;	
  4680                              <1> 	; Retro UNIX 8086 v1 modification: 
  4681                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4682                              <1> 	;	then branches into 'sysret'.
  4683                              <1> 	;
  4684 000043FF 66891D[40650000]    <1> 	mov	[u.quit], bx
  4685 00004406 E9F6ECFFFF          <1> 	jmp	sysret
  4686                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4687                              <1> 	;1:
  4688                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4689                              <1> 			      ; / to r1
  4690                              <1> 		; beq sysret4 / return to user
  4691                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4692                              <1> 			   ; / in the tty buffer
  4693                              <1> 		; br sysret4 / return to user
  4694                              <1> 
  4695                              <1> syssetuid: ; / set process id
  4696                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4697                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4698                              <1> 	;
  4699                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4700                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4701                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4702                              <1> 	; Only the super user can make this call.	
  4703                              <1> 	;
  4704                              <1> 	; Calling sequence:
  4705                              <1> 	;	syssetuid
  4706                              <1> 	; Arguments: -
  4707                              <1> 	;
  4708                              <1> 	; Inputs: (u.r0) - contains the process id.
  4709                              <1> 	; Outputs: -
  4710                              <1> 	; ...............................................................
  4711                              <1> 	;	
  4712                              <1> 	; Retro UNIX 8086 v1 modification: 
  4713                              <1> 	;       BL contains the (new) user ID of the current process
  4714                              <1> 
  4715                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4716 0000440B 3A1D[47650000]      <1> 	cmp	bl, [u.ruid] 
  4717                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4718                              <1> 			       ; / id number
  4719 00004411 741E                <1> 	je	short setuid1
  4720                              <1> 		; beq 1f / yes
  4721 00004413 803D[46650000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4722                              <1> 		; tstb u.uid / no, is current user the super user?
  4723                              <1> 	;ja	error
  4724                              <1> 		; bne error4 / no, error
  4725 0000441A 760F                <1> 	jna	short setuid0
  4726 0000441C C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4726 00004424 0000                <1>
  4727                              <1> 				; 'permission denied !' error
  4728 00004426 E9B6ECFFFF          <1> 	jmp	error
  4729                              <1> setuid0:
  4730 0000442B 881D[47650000]      <1> 	mov	[u.ruid], bl
  4731                              <1> setuid1: ; 1:
  4732 00004431 881D[46650000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4733                              <1> 		; movb r1,u.uid / put process id in u.uid
  4734                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4735 00004437 E9C5ECFFFF          <1> 	jmp	sysret
  4736                              <1> 		; br sysret4 / system return
  4737                              <1> 
  4738                              <1> sysgetuid: ; < get user id >
  4739                              <1> 	; 03/02/2022
  4740                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4741                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4742                              <1> 	;
  4743                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4744                              <1> 	; The real user ID identifies the person who is logged in,
  4745                              <1> 	; in contradistinction to the effective user ID, which
  4746                              <1> 	; determines his access permission at each moment. It is thus
  4747                              <1> 	; useful to programs which operate using the 'set user ID'
  4748                              <1> 	; mode, to find out who invoked them.	
  4749                              <1> 	;
  4750                              <1> 	; Calling sequence:
  4751                              <1> 	;	syssetuid
  4752                              <1> 	; Arguments: -
  4753                              <1> 	;
  4754                              <1> 	; Inputs: -
  4755                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4756                              <1> 	; ...............................................................
  4757                              <1> 	;	
  4758                              <1> 	; Retro UNIX 8086 v1 modification: 
  4759                              <1> 	;       AL contains the real user ID at return.
  4760                              <1> 	;
  4761                              <1> 	;movzx 	eax, byte [u.ruid]
  4762                              <1> 	; 03/03/2022
  4763 0000443C A0[47650000]        <1> 	mov	al, [u.ruid]
  4764 00004441 A3[00650000]        <1> 	mov	[u.r0], eax
  4765                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4766 00004446 E9B6ECFFFF          <1> 	jmp	sysret
  4767                              <1> 		; br sysret4 / systerm return, sysret
  4768                              <1> 
  4769                              <1> anyi: 
  4770                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4771                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4772                              <1> 	;
  4773                              <1> 	; 'anyi' is called if a file deleted while open.
  4774                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4775                              <1> 	;
  4776                              <1> 	; INPUTS ->
  4777                              <1> 	;    r1 - contains an i-number
  4778                              <1> 	;    fsp - start of table containing open files
  4779                              <1> 	;
  4780                              <1> 	; OUTPUTS ->
  4781                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4782                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4783                              <1> 	;    if file not found - bit in i-node map is cleared
  4784                              <1> 	;    			 (i-node is freed)
  4785                              <1> 	;               all blocks related to i-node are freed
  4786                              <1> 	;	        all flags in i-node are cleared
  4787                              <1> 	; ((AX = R1)) input
  4788                              <1> 	;
  4789                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4790                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4791                              <1> 	;
  4792                              <1> 		; / r1 contains an i-number
  4793 0000444B BB[C4620000]        <1> 	mov	ebx, fsp
  4794                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4795                              <1> anyi_1: ; 1:
  4796 00004450 663B03              <1> 	cmp	ax, [ebx]
  4797                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4798 00004453 7433                <1> 	je	short anyi_3
  4799                              <1> 		; beq 1f / yes, 1f
  4800 00004455 66F7D8              <1> 	neg	ax
  4801                              <1> 		; neg r1 / no complement r1
  4802 00004458 663B03              <1> 	cmp	ax, [ebx]
  4803                              <1> 		; cmp r1,(r2) / do they match now?
  4804 0000445B 742B                <1> 	je	short anyi_3
  4805                              <1> 		; beq 1f / yes, transfer
  4806                              <1> 		; / i-numbers do not match
  4807 0000445D 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4808                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4809                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4810 00004460 81FB[B8640000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4811                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4812                              <1> 				; / are we at last entry in the table
  4813 00004466 72E8                <1> 	jb	short anyi_1
  4814                              <1> 		; blt 1b / no, check next entries i-number
  4815                              <1> 	;cmp	ax, 32768
  4816 00004468 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4817                              <1> 		; tst r1 / yes, no match
  4818                              <1> 		; bge .+4
  4819 0000446B 7203                <1> 	jb	short anyi_2
  4820 0000446D 66F7D8              <1> 	neg	ax
  4821                              <1> 		; neg r1 / make i-number positive
  4822                              <1> anyi_2:	
  4823 00004470 E81A050000          <1> 	call	imap
  4824                              <1> 		; jsr r0,imap / get address of allocation bit 
  4825                              <1> 			    ; / in the i-map in r2
  4826                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4827                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4828                              <1>  	; not	dx
  4829 00004475 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4830                              <1>         ;and	[ebx], dx
  4831 00004477 2013                <1> 	and 	[ebx], dl 
  4832                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4833 00004479 E8A4040000          <1> 	call	itrunc
  4834                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4835 0000447E 66C705[F4610000]00- <1>  	mov 	word [i.flgs], 0
  4835 00004486 00                  <1>
  4836                              <1> 		; clr i.flgs / clear all flags in the i-node
  4837 00004487 C3                  <1> 	retn
  4838                              <1> 		;rts	r0 / return
  4839                              <1> anyi_3: ; 1: / i-numbers match
  4840 00004488 FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4841                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4842                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4843 0000448B C3                  <1> 	retn
  4844                              <1> 		; rts r0
  2054                                  %include 'u3.s'        ; 10/05/2015
  2055                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2056                              <1> ; Last Modification: 03/02/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 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2067                              <1> ;
  2068                              <1> ; ****************************************************************************
  2069                              <1> ; 15/09/2015
  2070                              <1> 
  2071                              <1> tswitch: ; Retro UNIX 386 v1
  2072                              <1> tswap:
  2073                              <1> 	; 01/09/2015
  2074                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2075                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2076                              <1> 	; time out swap, called when a user times out.
  2077                              <1> 	; the user is put on the low priority queue.
  2078                              <1> 	; This is done by making a link from the last user
  2079                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2080                              <1> 	; then he is swapped out.
  2081                              <1> 	;
  2082                              <1> 	; Retro UNIX 386 v1 modification ->
  2083                              <1> 	;       swap (software task switch) is performed by changing
  2084                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2085                              <1> 	;	as in Retro UNIX 8086 v1.
  2086                              <1> 	;
  2087                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2088                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2089                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2090                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2091                              <1> 	;	compatibles was using 1MB segmented memory 
  2092                              <1> 	;	in 8086/8088 times.
  2093                              <1> 	;
  2094                              <1> 	; INPUTS ->
  2095                              <1> 	;    u.uno - users process number
  2096                              <1> 	;    runq+4 - lowest priority queue
  2097                              <1> 	; OUTPUTS ->
  2098                              <1> 	;    r0 - users process number
  2099                              <1> 	;    r2 - lowest priority queue address
  2100                              <1> 	;
  2101                              <1> 	; ((AX = R0, BX = R2)) output
  2102                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2103                              <1> 	;
  2104 0000448C A0[49650000]        <1> 	mov 	al, [u.uno]
  2105                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2106                              <1> 		; mov  $runq+4,r2 
  2107                              <1> 			; / move lowest priority queue address to r2
  2108 00004491 E8CD000000          <1>         call 	putlu
  2109                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2110                              <1> 		             ; / u.uno's user
  2111                              <1> 
  2112                              <1> switch: ; Retro UNIX 386 v1
  2113                              <1> swap:
  2114                              <1> 	; 03/02/2022
  2115                              <1> 	; 02/09/2015
  2116                              <1> 	; 01/09/2015
  2117                              <1> 	; 31/08/2015
  2118                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2119                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2120                              <1> 	; 'swap' is routine that controls the swapping of processes
  2121                              <1> 	; in and out of core.
  2122                              <1> 	;
  2123                              <1> 	; Retro UNIX 386 v1 modification ->
  2124                              <1> 	;       swap (software task switch) is performed by changing
  2125                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2126                              <1> 	;	as in Retro UNIX 8086 v1.
  2127                              <1> 	;
  2128                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2129                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2130                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2131                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2132                              <1> 	;	compatibles was using 1MB segmented memory 
  2133                              <1> 	;	in 8086/8088 times.
  2134                              <1> 	;
  2135                              <1> 	; INPUTS ->
  2136                              <1> 	;    runq table - contains processes to run.
  2137                              <1> 	;    p.link - contains next process in line to be run.
  2138                              <1> 	;    u.uno - process number of process in core	
  2139                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2140                              <1> 	; OUTPUTS ->
  2141                              <1> 	;    (original unix v1 -> present process to its disk block)
  2142                              <1> 	;    (original unix v1 -> new process into core -> 
  2143                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2144                              <1> 	;	   for new process)
  2145                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2146                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2147                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2148                              <1> 	;	 for now, it will swap the process if there is not
  2149                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2150                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2151                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2152                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2153                              <1> 	;
  2154                              <1> 	;    u.pri -points to highest priority run Q.
  2155                              <1> 	;    r2 - points to the run queue.
  2156                              <1> 	;    r1 - contains new process number
  2157                              <1> 	;    r0 - points to place in routine or process that called
  2158                              <1> 	;	  swap all user parameters
  2159                              <1> 	;				
  2160                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2161                              <1> 	;
  2162                              <1> swap_0:
  2163                              <1> 		;mov $300,*$ps / processor priority = 6
  2164 00004496 BE[F0640000]        <1> 	mov	esi, runq
  2165                              <1> 		; mov $runq,r2 / r2 points to runq table
  2166                              <1> swap_1: ; 1: / search runq table for highest priority process
  2167 0000449B 668B06              <1> 	mov	ax, [esi]
  2168 0000449E 6621C0              <1> 	and 	ax, ax
  2169                              <1>        		; tst (r2)+ / are there any processes to run 
  2170                              <1> 			  ; / in this Q entry
  2171 000044A1 7507                <1> 	jnz	short swap_2
  2172                              <1>        		; bne 1f / yes, process 1f
  2173                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2174                              <1> 			       ; / to end of table
  2175                              <1> 		; bne 1b / if not at end, go back
  2176 000044A3 E8E0000000          <1> 	call	idle
  2177                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2178                              <1> 				       ; / all queues are empty
  2179 000044A8 EBF1                <1> 	jmp	short swap_1
  2180                              <1> 		; br swap
  2181                              <1> swap_2: ; 1:
  2182 000044AA 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2183                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2184                              <1>  		; mov r2,u.pri / set present user to this run queue
  2185                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2186 000044AD 38E0                <1> 	cmp	al, ah
  2187                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2188                              <1> 			      ; / in this Q to be run
  2189 000044AF 740A                <1> 	je	short swap_3
  2190                              <1>        		; beq 1f / yes
  2191                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2192                              <1> 	;movzx	ebx, al
  2193 000044B1 8AA3[63620000]      <1> 	mov	ah, [ebx+p.link-1] 
  2194 000044B7 8826                <1>        	mov	[esi], ah
  2195                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2196                              <1> 				       ; / in line into run queue
  2197 000044B9 EB05                <1> 	jmp	short swap_4
  2198                              <1>        		; br 2f
  2199                              <1> swap_3: ; 1:
  2200                              <1> 	;xor	dx, dx
  2201                              <1> 	; 03/02/2022
  2202 000044BB 31D2                <1> 	xor	edx, edx
  2203 000044BD 668916              <1> 	mov	[esi], dx
  2204                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2205                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2206                              <1>       ; / in new process if required
  2207                              <1>        		; clr *$ps / clear processor status
  2208 000044C0 8A25[49650000]      <1> 	mov 	ah, [u.uno]
  2209 000044C6 38C4                <1> 	cmp	ah, al
  2210                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2211                              <1> 			      ; / the process in core?
  2212 000044C8 743B                <1>        	je	short swap_8
  2213                              <1>        		; beq 2f / yes, don't have to swap
  2214                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2215                              <1> 			   ; / (address in routine that called swap)
  2216                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2217                              <1> 	; 01/09/2015
  2218                              <1> 	;mov	[u.usp], esp
  2219                              <1>        		; mov sp,u.usp / save stack pointer
  2220                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2221                              <1> 			       ; / to the stack pointer
  2222 000044CA 08E4                <1> 	or	ah, ah
  2223                              <1>        		; tstb u.uno / is the process # = 0
  2224 000044CC 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2225                              <1> 		; beq  1f / yes, kill process by overwriting
  2226                              <1> 	; 02/09/2015
  2227 000044CE 8925[FC640000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2228                              <1> 	;
  2229 000044D4 E834000000          <1> 	call	wswap
  2230                              <1> 		;jsr r0,wswap / write out core to disk
  2231                              <1> 	 ; 31/08/2015
  2232                              <1> 	;movzx	ebx, al ; New (running) process number
  2233 000044D9 EB1C                <1> 	jmp 	short swap_7
  2234                              <1> swap_6:
  2235                              <1> 	; 31/08/2015
  2236                              <1> 	; Deallocate memory pages belong to the process
  2237                              <1> 	; which is being terminated
  2238                              <1> 	; 14/05/2015 ('sysexit')
  2239                              <1>  	; Deallocate memory pages of the process
  2240                              <1> 	; (Retro UNIX 386 v1 modification !)
  2241                              <1> 	;
  2242                              <1> 	; movzx ebx, al
  2243 000044DB 53                  <1> 	push	ebx
  2244 000044DC A1[53650000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2245 000044E1 8B1D[57650000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2246 000044E7 E825E0FFFF          <1> 	call	deallocate_page_dir
  2247 000044EC A1[4A650000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2248 000044F1 E8B1E0FFFF          <1> 	call	deallocate_page
  2249 000044F6 5B                  <1> 	pop	ebx
  2250                              <1> swap_7: ;1: 
  2251                              <1> 	; 02/09/2015
  2252                              <1> 	; 31/08/2015
  2253                              <1> 	; 14/05/2015
  2254 000044F7 C0E302              <1> 	shl	bl, 2 ; * 4 
  2255 000044FA 8B83[80620000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2256                              <1> 	;cli
  2257 00004500 E831000000          <1> 	call	rswap
  2258                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2259                              <1> 		; jsr r0,rswap / read new process into core
  2260                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2261                              <1> 			      ; / to his program to its normal
  2262                              <1> 	; 01/09/2015
  2263                              <1> 	;mov	esp, [u.usp]	
  2264                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2265                              <1> 			     ; / new process stack
  2266                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2267                              <1> 			     ; / that just got swapped in, left off.,
  2268                              <1> 			     ; / i.e., transfer control to new process
  2269                              <1> 	;sti
  2270                              <1> swap_8: ;2:
  2271                              <1> 	; RETRO UNIX 8086 v1 modification !
  2272 00004505 C605[3C650000]04    <1> 	mov	byte [u.quant], time_count 
  2273                              <1> 		; movb $30.,uquant / initialize process time quantum
  2274 0000450C C3                  <1> 	retn
  2275                              <1> 		; rts r0 / return
  2276                              <1> 
  2277                              <1> wswap:  ; < swap out, swap to disk >
  2278                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2279                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2280                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2281                              <1> 	; appropriate disk area.
  2282                              <1> 	;
  2283                              <1> 	; Retro UNIX 386 v1 modification ->
  2284                              <1> 	;       User (u) structure content and the user's register content
  2285                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2286                              <1> 	;	saving 'u' structure and user registers for task switching).
  2287                              <1> 	;	u.usp - points to kernel stack address which contains
  2288                              <1> 	;		user's registers while entering system call.  
  2289                              <1> 	;	u.sp  - points to kernel stack address 
  2290                              <1> 	;		to return from system call -for IRET-.
  2291                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2292                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2293                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2294                              <1> 	;
  2295                              <1> 	; Retro UNIX 8086 v1 modification ->
  2296                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2297                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2298                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2299                              <1> 	;	compatibles was using 1MB segmented memory 
  2300                              <1> 	;	in 8086/8088 times.
  2301                              <1> 	;
  2302                              <1> 	; INPUTS ->
  2303                              <1> 	;    u.break - points to end of program
  2304                              <1> 	;    u.usp - stack pointer at the moment of swap
  2305                              <1> 	;    core - beginning of process program		
  2306                              <1> 	;    ecore - end of core 	
  2307                              <1> 	;    user - start of user parameter area		
  2308                              <1> 	;    u.uno - user process number	
  2309                              <1> 	;    p.dska - holds block number of process	
  2310                              <1> 	; OUTPUTS ->
  2311                              <1> 	;    swp I/O queue
  2312                              <1> 	;    p.break - negative word count of process 
  2313                              <1> 	;    r1 - process disk address	
  2314                              <1> 	;    r2 - negative word count
  2315                              <1> 	;
  2316                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2317                              <1> 	;
  2318                              <1> 	; INPUTS ->
  2319                              <1> 	;    u.uno - process number (to be swapped out)
  2320                              <1> 	; OUTPUTS ->
  2321                              <1> 	;    none
  2322                              <1> 	;
  2323                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2324                              <1> 	;
  2325 0000450D 8B3D[4A650000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2326 00004513 B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2327 00004518 BE[F8640000]        <1> 	mov	esi, user ; active user (u) structure	
  2328 0000451D F3A5                <1> 	rep	movsd
  2329                              <1> 	;
  2330 0000451F 8B35[FC640000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2331                              <1> 			     ;      points to user registers)
  2332 00004525 8B0D[F8640000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2333                              <1> 			     ; (for IRET)
  2334                              <1> 			     ; [u.sp] -> EIP (user)
  2335                              <1> 			     ; [u.sp+4]-> CS (user)
  2336                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2337                              <1> 			     ; [u.sp+12] -> ESP (user)
  2338                              <1> 			     ; [u.sp+16] -> SS (user)	
  2339 0000452B 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2340 0000452D 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2341                              <1> 			     ; (for IRET) 	
  2342 00004530 C1E902              <1> 	shr	ecx, 2	     		
  2343 00004533 F3A5                <1> 	rep	movsd
  2344 00004535 C3                  <1> 	retn
  2345                              <1> 
  2346                              <1> 	; Original UNIX v1 'wswap' routine:
  2347                              <1> 	; wswap:
  2348                              <1> 		; mov *$30,u.emt / determines handling of emts
  2349                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2350                              <1> 				; / illegal instructions
  2351                              <1> 		; mov u.break,r2 / put process program break address in r2
  2352                              <1> 		; inc r2 / add 1 to it 
  2353                              <1> 		; bic $1,r2 / make it even
  2354                              <1> 		; mov r2,u.break / set break to an even location
  2355                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2356                              <1> 			     ; / at moment of swap in r3
  2357                              <1> 		; cmp r2,$core / is u.break less than $core
  2358                              <1> 		; blos 2f / yes
  2359                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2360                              <1>        		; bhis 2f / yes
  2361                              <1> 	; 1:
  2362                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2363                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2364                              <1> 		; bne 1b / no, keep packing
  2365                              <1> 	 	; br 1f / yes
  2366                              <1> 	; 2:
  2367                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2368                              <1> 	; 1:
  2369                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2370                              <1> 			   ; / (user up to end of stack gets written out)
  2371                              <1> 		; neg r2 / make it negative
  2372                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2373                              <1> 		; mov r2,swp+4 / word count
  2374                              <1> 		; movb u.uno,r1 / move user process number to r1
  2375                              <1> 		; asl r1 / x2 for index
  2376                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2377                              <1> 				     ; / into the p.break table
  2378                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2379                              <1> 				    ; /	for process to r1
  2380                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2381                              <1> 			     ; / (block number)
  2382                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2383                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2384                              <1> 	; 1:
  2385                              <1>        		; tstb swp+1 / is lt done writing?
  2386                              <1>        		; bne 1b / no, wait
  2387                              <1> 		; rts r0 / yes, return to swap
  2388                              <1> 
  2389                              <1> rswap:  ; < swap in, swap from disk >
  2390                              <1> 	; 15/09/2015
  2391                              <1> 	; 28/08/2015
  2392                              <1> 	; 14/05/2015
  2393                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2394                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2395                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2396                              <1> 	; from disk into core.
  2397                              <1> 	;
  2398                              <1> 	; Retro UNIX 386 v1 modification ->
  2399                              <1> 	;       User (u) structure content and the user's register content
  2400                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2401                              <1> 	;	saving 'u' structure and user registers for task switching).
  2402                              <1> 	;	u.usp - points to kernel stack address which contains
  2403                              <1> 	;		user's registers while entering system call.  
  2404                              <1> 	;	u.sp  - points to kernel stack address 
  2405                              <1> 	;		to return from system call -for IRET-.
  2406                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2407                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2408                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2409                              <1> 	;
  2410                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2411                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2412                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2413                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2414                              <1> 	;	compatibles was using 1MB segmented memory 
  2415                              <1> 	;	in 8086/8088 times.
  2416                              <1> 	;
  2417                              <1> 	; INPUTS ->
  2418                              <1> 	;    r1 - process number of process to be read in
  2419                              <1> 	;    p.break - negative of word count of process 
  2420                              <1> 	;    p.dska - disk address of the process		
  2421                              <1> 	;    u.emt - determines handling of emt's 	
  2422                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2423                              <1> 	; OUTPUTS ->
  2424                              <1> 	;    8 = (u.ilgins)
  2425                              <1> 	;    24 = (u.emt)
  2426                              <1> 	;    swp - bit 10 is set to indicate read 
  2427                              <1> 	;		(bit 15=0 when reading is done)	
  2428                              <1> 	;    swp+2 - disk block address
  2429                              <1> 	;    swp+4 - negative word count 	
  2430                              <1> 	;      ((swp+6 - address of user structure)) 
  2431                              <1> 	;
  2432                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2433                              <1> 	;
  2434                              <1> 	; INPUTS ->
  2435                              <1> 	;    AL	- new process number (to be swapped in)	 
  2436                              <1> 	; OUTPUTS ->
  2437                              <1> 	;    none
  2438                              <1> 	;
  2439                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2440                              <1> 	;
  2441                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2442 00004536 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2443 00004538 B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2444 0000453D BF[F8640000]        <1> 	mov	edi, user ; active user (u) structure	
  2445 00004542 F3A5                <1> 	rep	movsd
  2446 00004544 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2447 00004545 8B3D[FC640000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2448                              <1> 			     ;      points to user registers)
  2449 0000454B 8B0D[F8640000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2450                              <1> 			     ; (for IRET)
  2451                              <1> 			     ; [u.sp] -> EIP (user)
  2452                              <1> 			     ; [u.sp+4]-> CS (user)
  2453                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2454                              <1> 			     ; [u.sp+12] -> ESP (user)
  2455                              <1> 			     ; [u.sp+16] -> SS (user)		
  2456                              <1> 	; 28/08/2015
  2457 00004551 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2458 00004553 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2459                              <1> 			     ; (for IRET) 	
  2460 00004556 C1E902              <1> 	shr	ecx, 2	       		
  2461 00004559 F3A5                <1> 	rep	movsd
  2462 0000455B 8B25[FC640000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2463 00004561 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2464 00004562 C3                  <1> 	retn
  2465                              <1> 
  2466                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2467                              <1> 	;rswap:
  2468                              <1>        		; asl r1 / process number x2 for index
  2469                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2470                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2471                              <1>        		; bis $2000,swp / read
  2472                              <1>        		; jsr r0,ppoke / read it in 
  2473                              <1> 	; 1:
  2474                              <1>        		; tstb swp+1 / done
  2475                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2476                              <1>        		; mov u.emt,*$30 / yes move these
  2477                              <1>        		; mov u.ilgins,*$10 / back
  2478                              <1>        		; rts r0 / return
  2479                              <1> 
  2480                              <1> 	;unpack: ; / move stack back to its normal place
  2481                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2482                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2483                              <1> 		; blos 2f / yes, return
  2484                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2485                              <1> 			     ; / before swapping
  2486                              <1> 		; bhis 2f / yes, return
  2487                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2488                              <1> 		; add r3,r2
  2489                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2490                              <1> 	; 1:
  2491                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2492                              <1> 		; cmp r2,u.break / in core
  2493                              <1> 		; bne 1b
  2494                              <1> 	; 2:
  2495                              <1>        		; rts r0
  2496                              <1> 
  2497                              <1> putlu: 
  2498                              <1> 	; 12/09/2015
  2499                              <1> 	; 02/09/2015
  2500                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2501                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2502                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2503                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2504                              <1> 	; the last process on the queue to process in r1 by putting
  2505                              <1> 	; the process number in r1 into the last process's link.
  2506                              <1> 	;
  2507                              <1> 	; INPUTS ->
  2508                              <1> 	;    r1 - user process number
  2509                              <1> 	;    r2 - points to lowest priority queue 
  2510                              <1> 	;    p.dska - disk address of the process		
  2511                              <1> 	;    u.emt - determines handling of emt's 	
  2512                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2513                              <1> 	; OUTPUTS ->
  2514                              <1> 	;    r3 - process number of last process on the queue upon
  2515                              <1> 	;	  entering putlu
  2516                              <1> 	;    p.link-1 + r3 - process number in r1
  2517                              <1> 	;    r2 - points to lowest priority queue
  2518                              <1> 	;
  2519                              <1> 	; ((Modified registers: EDX, EBX)) 
  2520                              <1> 	;
  2521                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2522                              <1> 
  2523                              <1> 	; eBX = r2
  2524                              <1> 	; eAX = r1 (AL=r1b)
  2525                              <1> 
  2526 00004563 BB[F0640000]        <1> 	mov	ebx, runq
  2527 00004568 0FB613              <1> 	movzx  	edx, byte [ebx]
  2528 0000456B 43                  <1> 	inc	ebx
  2529 0000456C 20D2                <1> 	and	dl, dl
  2530                              <1> 		; tstb (r2)+ / is queue empty?
  2531 0000456E 740A                <1>        	jz	short putlu_1
  2532                              <1> 		; beq 1f / yes, branch
  2533 00004570 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2534                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2535                              <1> 			     ; / in r3
  2536 00004572 8882[63620000]      <1>        	mov	[edx+p.link-1], al
  2537                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2538                              <1> 			     ; / "last users" link
  2539 00004578 EB03                <1> 	jmp	short putlu_2
  2540                              <1> 		; br 2f /
  2541                              <1> putlu_1: ; 1:
  2542 0000457A 8843FF              <1> 	mov	[ebx-1], al
  2543                              <1>        		; movb r1,-1(r2) / user is only user; 
  2544                              <1> 			    ; / put process no. at beginning and at end
  2545                              <1> putlu_2: ; 2: 
  2546 0000457D 8803                <1> 	mov	[ebx], al
  2547                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2548                              <1> 			     ; / on the queue
  2549 0000457F 88C2                <1> 	mov	dl, al
  2550 00004581 88B2[63620000]      <1>         mov     [edx+p.link-1], dh ; 0
  2551                              <1> 		; dec r2 / restore r2
  2552 00004587 C3                  <1>         retn
  2553                              <1> 		; rts r0
  2554                              <1> 
  2555                              <1> ;copyz:
  2556                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2557                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2558                              <1> ;       mov     (r0)+,r1
  2559                              <1> ;       mov     (r0)+,r2
  2560                              <1> ;1:
  2561                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2562                              <1> ;       cmp     r1,r2 
  2563                              <1> ;       blo     1b
  2564                              <1> ;       mov     (sp)+,r2 / restore r2
  2565                              <1> ;       mov     (sp)+,r1 / restore r1
  2566                              <1> ;       rts     r0 
  2567                              <1> 
  2568                              <1> idle:
  2569                              <1> 	; 01/09/2015
  2570                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2571                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2572                              <1> 	; (idle & wait loop)
  2573                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2574                              <1> 	; idle procedure!
  2575                              <1>       	;
  2576                              <1>   	; 01/09/2015
  2577 00004588 FB                  <1> 	sti
  2578                              <1>       	; 29/07/2013
  2579 00004589 F4                  <1>       	hlt
  2580 0000458A 90                  <1>       	nop ; 10/10/2013
  2581 0000458B 90                  <1>       	nop
  2582 0000458C 90                  <1>       	nop
  2583                              <1>       	; 23/10/2013
  2584 0000458D 90                  <1>       	nop
  2585 0000458E 90                  <1>       	nop
  2586 0000458F 90                  <1>       	nop
  2587 00004590 90                  <1>       	nop
  2588 00004591 C3                  <1>       	retn      
  2589                              <1> 
  2590                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2591                              <1> 	;clr *$ps / clear ps
  2592                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2593                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2594                              <1> 	;1 / wait for interrupt
  2595                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2596                              <1> 	;mov (sp)+,*$ps
  2597                              <1> 	;rts r0
  2598                              <1> 
  2599                              <1> clear:
  2600                              <1> 	; 03/02/2022
  2601                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2602                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2603                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2604                              <1> 	; on the current device (cdev)
  2605                              <1> 	;	
  2606                              <1> 	; INPUTS ->
  2607                              <1> 	;    r1 - block number of block to be zeroed
  2608                              <1> 	;    cdev - current device number 
  2609                              <1> 	; OUTPUTS ->
  2610                              <1> 	;    a zeroed I/O buffer onto the current device
  2611                              <1> 	;    r1 - points to last entry in the I/O buffer
  2612                              <1> 	;
  2613                              <1> 	; ((AX = R1)) input/output
  2614                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2615                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2616                              <1> 
  2617 00004592 E88E0E0000          <1> 	call 	wslot
  2618                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2619                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2620 00004597 89DF                <1> 	mov	edi, ebx ; r5
  2621 00004599 89C2                <1> 	mov	edx, eax
  2622 0000459B B980000000          <1> 	mov	ecx, 128
  2623                              <1> 		; mov $256.,r3
  2624 000045A0 31C0                <1> 	xor	eax, eax
  2625 000045A2 F3AB                <1> 	rep	stosd
  2626 000045A4 89D0                <1> 	mov	eax, edx
  2627                              <1> ; 1: 
  2628                              <1>        		; clr (r5)+ / zero data word in buffer
  2629                              <1>        		; dec r3
  2630                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2631                              <1> 	;call	dskwr
  2632                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2633                              <1>                              ; / block specified in r1
  2634                              <1> 	; eAX (r1) = block number
  2635                              <1> 	;retn
  2636                              <1> 		; rts r0
  2637                              <1> 	; 03/02/2022
  2638 000045A6 E9870E0000          <1> 	jmp	dskwr
  2055                                  %include 'u4.s'        ; 15/04/2015
  2056                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2057                              <1> ; Last Modification: 26/02/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 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2068                              <1> ;
  2069                              <1> ; ****************************************************************************
  2070                              <1> ; 14/10/2015
  2071                              <1> 
  2072                              <1> ;setisp:
  2073                              <1>        ;mov     r1,-(sp)
  2074                              <1>        ;mov     r2,-(sp)
  2075                              <1>        ;mov     r3,-(sp)
  2076                              <1>        ;mov     clockp,-(sp)
  2077                              <1>        ;mov     $s.syst+2,clockp
  2078                              <1>        ;jmp     (r0)
  2079                              <1> 
  2080                              <1> clock: ; / interrupt from 60 cycle clock
  2081                              <1> 	
  2082                              <1> 	; 14/10/2015
  2083                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2084                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2085                              <1> 
  2086                              <1>        ;mov     r0,-(sp) / save r0
  2087                              <1>        ;tst     *$lks / restart clock?
  2088                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2089                              <1>        ;inc     (r0)
  2090                              <1>        ;bne     1f
  2091                              <1>        ;inc     -(r0)
  2092                              <1> ;1:
  2093                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2094                              <1>        ;inc     (r0)
  2095                              <1>        ;bne     1f
  2096                              <1>        ;inc     -(r0)
  2097                              <1> ;1:
  2098                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2099                              <1> 
  2100 000045AB 803D[3C650000]00    <1> 	cmp	byte [u.quant], 0
  2101 000045B2 772C                <1> 	ja	short clk_1
  2102                              <1> 	;
  2103 000045B4 803D[F5640000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2104 000045BB 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2105 000045BD 803D[49650000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2106 000045C4 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2107 000045C6 66833D[3E650000]00  <1> 	cmp	word [u.intr], 0
  2108 000045CE 7616                <1> 	jna	short clk_2
  2109                              <1> clk_0:
  2110                              <1> 	; 14/10/2015
  2111 000045D0 FE05[F5640000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2112 000045D6 58                  <1> 	pop	eax ; return address to the timer interrupt
  2113                              <1> 	;
  2114 000045D7 B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2115                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2116 000045D9 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2117                              <1> 	;
  2118 000045DB E97DEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2119                              <1> clk_1:
  2120 000045E0 FE0D[3C650000]      <1> 	dec	byte [u.quant]
  2121                              <1> clk_2:
  2122 000045E6 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2123                              <1> 
  2124                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2125                              <1> 
  2126                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2127                              <1>        ;decb    (r0)
  2128                              <1>        ;bge     1f / if less than 0
  2129                              <1>        ;clrb    (r0) / make it 0
  2130                              <1> ;1: / decrement time out counts return now if priority was not 0
  2131                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2132                              <1>        ;bge     2f / yes, check time outs
  2133                              <1>        ;tstb    (r0) / no, user timed out?
  2134                              <1>        ;bne     1f / no
  2135                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2136                              <1>        ;bne     1f / no, 1f
  2137                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2138                              <1>        ;sys     0 / sysrele
  2139                              <1>        ;rti
  2140                              <1> ;2: / priority is high so just decrement time out counts
  2141                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2142                              <1> ;2:
  2143                              <1>        ;tstb    (r0) / is the time out?
  2144                              <1>        ;beq     3f / yes, 3f (get next entry)
  2145                              <1>        ;decb    (r0) / no, decrement the time
  2146                              <1>        ;bne     3f / isit zero now?
  2147                              <1>        ;incb    (r0) / yes, increment the time
  2148                              <1> ;3:
  2149                              <1>        ;inc     r0 / next entry
  2150                              <1>        ;cmp     r0,$touts / end of toutt table?
  2151                              <1>        ;blo     2b / no, check this entry
  2152                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2153                              <1>        ;rti / return from interrupt
  2154                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2155                              <1>        ;mov     (sp)+,r0 / restore r0
  2156                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2157                              <1>        ;jsr     r0,setisp / save registers
  2158                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2159                              <1>                                ;  / the table
  2160                              <1> ;1:
  2161                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2162                              <1>        ;beq     2f / yes
  2163                              <1>        ;decb    toutt(r0) / no, decrement the time
  2164                              <1>        ;bne     2f / is the time 0, now
  2165                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2166                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2167                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2168                              <1> ;2:
  2169                              <1>        ;dec     r0 / set up r0 for next entry
  2170                              <1>        ;bge     1b / finished? , no, go back
  2171                              <1>        ;br      retisp / yes, restore registers and do a rti
  2172                              <1> 
  2173                              <1> ;retisp:
  2174                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2175                              <1>        ;mov     (sp)+,r3
  2176                              <1>        ;mov     (sp)+,r2
  2177                              <1>        ;mov     (sp)+,r1
  2178                              <1>        ;mov     (sp)+,r0
  2179                              <1>        ;rti     / return from interrupt
  2180                              <1> 
  2181                              <1> 
  2182                              <1> wakeup: ; / wakeup processes waiting for an event 
  2183                              <1> 	; / by linking them to the queue
  2184                              <1> 	;
  2185                              <1> 	; 26/02/2022
  2186                              <1> 	; 15/09/2015
  2187                              <1> 	; 29/06/2015
  2188                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2189                              <1> 	;
  2190                              <1> 	; 15/05/2013 - 02/06/2014
  2191                              <1> 	; Retro UNIX 8086 v1 modification !
  2192                              <1> 	; (Process/task switching routine by using
  2193                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2194                              <1> 	;
  2195                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2196                              <1> 	; sleeping in the specified wait channel by creating a link 
  2197                              <1> 	; to it from the last user process on the run queue.
  2198                              <1> 	; If there is no process to wake up, nothing happens.
  2199                              <1> 	;
  2200                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2201                              <1> 	; 'switching' status of the current process (owns current tty)
  2202                              <1> 	; (via alt + function keys) to a process which has highest
  2203                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2204                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2205                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2206                              <1> 	; tty for tty switching by keyboard.)	 
  2207                              <1> 	; 
  2208                              <1> 	; INPUT -> 
  2209                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2210                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2211                              <1> 	;
  2212                              <1> 	; ((modified registers: EAX, EBX))
  2213                              <1> 	;
  2214 000045E7 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2215 000045EA 81C3[98610000]      <1> 	add	ebx, wlist
  2216 000045F0 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2217 000045F2 20C0                <1> 	and	al, al
  2218 000045F4 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2219                              <1> 	;
  2220 000045F6 30E4                <1> 	xor	ah, ah
  2221 000045F8 8825[3C650000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2222 000045FE 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2223                              <1> 	; 15/09/2015
  2224 00004600 0FB6D8              <1> 	movzx	ebx, al
  2225                              <1> 	; 26/02/2022 (p.waitc is not used)
  2226                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2227 00004603 FEC4                <1> 	inc	ah
  2228 00004605 88A3[73620000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2229                              <1> 	;
  2230 0000460B 57                  <1> 	push	edi
  2231 0000460C 52                  <1> 	push	edx
  2232 0000460D E851FFFFFF          <1> 	call	putlu
  2233 00004612 5A                  <1> 	pop	edx
  2234 00004613 5F                  <1> 	pop	edi
  2235                              <1> wa0:
  2236 00004614 C3                  <1> 	retn
  2237                              <1> 
  2238                              <1> sleep: 
  2239                              <1> 	; 26/02/2022
  2240                              <1> 	; 03/02/2022
  2241                              <1> 	; 15/09/2015
  2242                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2243                              <1> 	;
  2244                              <1> 	; 09/05/2013 - 20/03/2014
  2245                              <1> 	;
  2246                              <1> 	; Retro UNIX 8086 v1 modification !
  2247                              <1> 	; (Process/task switching and quit routine by using
  2248                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2249                              <1> 	;
  2250                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2251                              <1> 	; tty and tape output or input becomes available
  2252                              <1> 	; and process is put on waiting channel and swapped out,
  2253                              <1> 	; then -when the tty or tape is ready to write or read-
  2254                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2255                              <1> 	;
  2256                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2257                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2258                              <1> 	; status of the current process also INT 1Ch will count down
  2259                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2260                              <1> 	; to tty buffer of the current process and kernel will get
  2261                              <1> 	; user input by using tty buffer of the current process
  2262                              <1> 	; (instead of standard INT 16h interrupt).
  2263                              <1> 	; TTY output will be redirected to related video page of text mode
  2264                              <1> 	; (INT 10h will be called with different video page depending
  2265                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2266                              <1> 	; pseudo screens.)
  2267                              <1> 	;
  2268                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2269                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2270                              <1> 	; characters/data on serial port(s).
  2271                              <1> 	;
  2272                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2273                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2274                              <1> 	; 
  2275                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2276                              <1> 	;
  2277                              <1> 	;; 05/10/2013
  2278                              <1>         ;10/12/2013
  2279                              <1> 	;cmp   byte [u.uno], 1
  2280                              <1>         ;ja    short sleep0
  2281                              <1> 	;retn
  2282                              <1> 
  2283                              <1> 	; 20/03/2014
  2284                              <1> 	;mov	bx, [runq]
  2285                              <1> 	;cmp	bl, bh
  2286                              <1> 	;jne	short sleep0	
  2287                              <1> 	; 25/02/2014
  2288                              <1> 	;cmp word ptr [runq], 0
  2289                              <1> 	;ja short sleep0	
  2290                              <1> 	;retn
  2291                              <1> sleep0:
  2292                              <1> 	;
  2293 00004615 E849000000          <1> 	call	isintr
  2294                              <1> 	;jnz	sysret
  2295                              <1> 		; / wait for event
  2296                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2297                              <1> 			      ; / or quit from user
  2298                              <1>                		; br 2f / something happened
  2299                              <1> 			      ; / yes, his interrupt so return
  2300                              <1>                      	      ;	/ to user
  2301                              <1> 	; 03/02/2022
  2302 0000461A 7405                <1> 	jz	short sleep_2
  2303                              <1> sleep_3:
  2304 0000461C E9E0EAFFFF          <1> 	jmp	sysret
  2305                              <1> sleep_2:
  2306                              <1> 	; 30/06/2015
  2307 00004621 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2308 00004624 81C3[98610000]      <1> 	add	ebx, wlist
  2309 0000462A 8A03                <1> 	mov	al, [ebx]
  2310 0000462C 20C0                <1> 	and	al, al
  2311 0000462E 7407                <1> 	jz	short sleep1
  2312 00004630 53                  <1> 	push	ebx
  2313 00004631 E82DFFFFFF          <1> 	call	putlu
  2314 00004636 5B                  <1> 	pop	ebx
  2315                              <1> sleep1:
  2316 00004637 A0[49650000]        <1> 	mov	al, [u.uno]    
  2317 0000463C 8803                <1>   	mov	[ebx], al 	; put the process number
  2318                              <1> 				; in the wait channel
  2319                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2320                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2321                              <1> 				     ; / on the stack
  2322                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2323                              <1> 				     ; / to put to sleep in there
  2324                              <1>         ; 15/09/2015
  2325 0000463E 0FB6D8              <1> 	movzx	ebx, al
  2326 00004641 C683[73620000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2327                              <1> 	; 26/02/2022 (p.waitc is not used)
  2328                              <1> 	;inc	ah
  2329                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2330                              <1> 	;
  2331 00004648 66FF35[E4640000]    <1> 	push    word [cdev]
  2332                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2333 0000464F E842FEFFFF          <1> 	call	swap
  2334                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2335 00004654 668F05[E4640000]    <1>         pop     word [cdev]
  2336                              <1> 		; mov (sp)+,cdev / restore device
  2337 0000465B E803000000          <1> 	call	isintr
  2338                              <1> 	; 22/09/2013
  2339                              <1> 	;jnz	sysret         
  2340                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2341                              <1>                		; br 2f / yes, return to new user
  2342                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2343                              <1> 				; / originally on the wait channel
  2344                              <1>        		; beq 1f / if 0 branch
  2345                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2346                              <1>        		; mov $300,*$ps / processor priority = 6
  2347                              <1> 		; jsr r0,putlu / create link to old process number
  2348                              <1>        		; clr *$ps / clear the status; process priority = 0
  2349                              <1> 	; 03/02/2022
  2350 00004660 75BA                <1> 	jnz	short sleep_3
  2351                              <1>      ;1:
  2352 00004662 C3                  <1> 	retn
  2353                              <1> 		; rts r0 / return
  2354                              <1>      ;2:
  2355                              <1>         ;;jmp	sysret
  2356                              <1> 		; jmp sysret / return to user
  2357                              <1> 
  2358                              <1> isintr:
  2359                              <1> 	; 03/02/2022
  2360                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2361                              <1> 	;
  2362                              <1> 	; 09/05/2013 - 30/05/2014
  2363                              <1> 	;
  2364                              <1> 	; Retro UNIX 8086 v1 modification !
  2365                              <1> 	; (Process/task switching and quit routine by using
  2366                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2367                              <1> 	;
  2368                              <1> 	; Retro UNIX 8086 v1 modification:
  2369                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2370                              <1> 	;  and there is a 'quit' request by user;
  2371                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2372                              <1> 	;  "nothing to do". (20/10/2013)
  2373                              <1> 	;
  2374                              <1> 	; 20/10/2013
  2375 00004663 66833D[30650000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2376 0000466B 761F                <1> 	jna	short isintr2 ; retn
  2377                              <1> 	; 03/09/2013
  2378                              <1> 	; (nothing to do)
  2379                              <1> 	;retn
  2380                              <1> 	; 22/09/2013
  2381 0000466D 66833D[3E650000]00  <1> 	cmp	word [u.intr], 0
  2382 00004675 7615                <1> 	jna	short isintr2 ; retn
  2383                              <1> 	; 30/05/2014
  2384                              <1> 	;push	ax
  2385                              <1> 	; 03/02/2022
  2386 00004677 50                  <1> 	push	eax
  2387 00004678 66A1[40650000]      <1> 	mov	ax, [u.quit]
  2388 0000467E 6609C0              <1> 	or	ax, ax ; 0 ?
  2389 00004681 7408                <1> 	jz	short isintr1 ; zf = 1
  2390 00004683 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2391 00004687 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2392                              <1> 	;xor	ax, ax ; zf = 1
  2393                              <1> 	; 03/02/2022
  2394 00004689 31C0                <1> 	xor	eax, eax ; zf = 1
  2395                              <1> isintr1:
  2396                              <1> 	;pop	ax
  2397                              <1> 	; 03/02/2022
  2398 0000468B 58                  <1> 	pop	eax
  2399                              <1> isintr2: ; 22/09/2013
  2400                              <1> 	; zf=1 -> nothing to do
  2401 0000468C C3                  <1> 	retn
  2402                              <1> 
  2403                              <1> 	; UNIX v1 original 'isintr' routine... 
  2404                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2405                              <1>        	;mov     r2,-(sp) / save r2
  2406                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2407                              <1>         ;                 / typewriter
  2408                              <1>        	;beq     1f / if 0, do nothing except skip return
  2409                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2410                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2411                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2412                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2413                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2414                              <1>         ;              / of interrupts
  2415                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2416                              <1>      ;1:
  2417                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2418                              <1>      ;4:
  2419                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2420                              <1>        	;mov     (sp)+,r1
  2421                              <1>        	;rts     r0
  2422                              <1>      ;3: / interrupt char = quit (fs)
  2423                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2424                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2425                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2426                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2427                              <1>      ;1: / find process control tty entry in tty block
  2428                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2429                              <1>        	;beq     1f / block found go to 1f
  2430                              <1>        	;add     $8,r1 / look at next tty block
  2431                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2432                              <1>        	;blo     1b / no
  2433                              <1>        	;br      4b / no process control tty found so go to 4b
  2434                              <1>      ;1:
  2435                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2436                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2437                              <1>         ;                  / identifier
  2438                              <1>        	;inc     0f / increment
  2439                              <1>      ;1:
  2440                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2441                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2442                              <1>         ;             / being typed out after you hit the interrupt
  2443                              <1>         ;             / key
  2444                              <1>        	;br      1b
  2056                                  %include 'u5.s'        ; 03/06/2015
  2057                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2058                              <1> ; Last Modification: 22/04/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 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2069                              <1> ;
  2070                              <1> ; ****************************************************************************
  2071                              <1> ; 14/11/2015
  2072                              <1> 
  2073                              <1> mget:
  2074                              <1> 	; 22/04/2022
  2075                              <1> 	; 03/02/2022
  2076                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2077                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2078                              <1> 	;
  2079                              <1> 	; Get existing or (allocate) a new disk block for file
  2080                              <1> 	; 
  2081                              <1> 	; INPUTS ->
  2082                              <1> 	;    u.fofp (file offset pointer)
  2083                              <1> 	;    inode 
  2084                              <1> 	;    u.off (file offset)
  2085                              <1> 	; OUTPUTS ->
  2086                              <1> 	;    r1 (physical block number)
  2087                              <1> 	;    r2, r3, r5 (internal)
  2088                              <1> 	;
  2089                              <1> 	; ((AX = R1)) output
  2090                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2091                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2092                              <1> 
  2093                              <1> 		; mov *u.fofp,mq / file offset in mq
  2094                              <1> 		; clr ac / later to be high sig
  2095                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2096                              <1> 		; mov mq,r2
  2097                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2098                              <1> 		; bne 4f / branch for large file
  2099                              <1> mget_0:	
  2100                              <1> 	; 03/02/2022
  2101 0000468D 29C0                <1> 	sub	eax, eax
  2102 0000468F 29D2                <1> 	sub	edx, edx
  2103 00004691 29C9                <1> 	sub	ecx, ecx
  2104 00004693 29DB                <1> 	sub	ebx, ebx
  2105                              <1> 
  2106 00004695 8B35[10650000]      <1>         mov     esi, [u.fofp]
  2107                              <1>         ;movzx	ebx, byte [esi+1]
  2108                              <1> 	; 03/02/2022
  2109 0000469B 46                  <1> 	inc	esi
  2110 0000469C 8A1E                <1> 	mov	bl, [esi]
  2111                              <1> 
  2112                              <1> 	; BX = r2
  2113                              <1> 	; 03/02/2022
  2114 0000469E F605[F5610000]10    <1> 	test	byte [i.flgs+1], 10h
  2115                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2116                              <1> 			  	     ; is this a large or small file
  2117 000046A5 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2118                              <1> 
  2119 000046A7 F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2120                              <1> 		; bit $!17,r2
  2121 000046AA 7525                <1> 	jnz 	short mget_2
  2122                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2123 000046AC 80E30E              <1>         and     bl, 0Eh  
  2124                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2125                              <1> 	; 03/02/2022
  2126 000046AF 668B83[FA610000]    <1> 	mov	ax, [ebx+i.dskp]
  2127                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2128                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2129                              <1> 	; 03/02/2022
  2130 000046B6 09C0                <1> 	or	eax, eax
  2131                              <1> 	;or 	ax, ax
  2132 000046B8 7516                <1> 	jnz 	short mget_1 
  2133                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2134                              <1> 		       ; / for file
  2135 000046BA E8A6000000          <1> 	call 	alloc
  2136                              <1> 		; jsr r0,alloc / allocate a new block
  2137                              <1>          ; eAX (r1) = Physical block number
  2138 000046BF 668983[FA610000]    <1> 	mov 	[ebx+i.dskp], ax
  2139                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2140 000046C6 E835020000          <1> 	call 	setimod	
  2141                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2142 000046CB E8C2FEFFFF          <1> 	call	clear
  2143                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2144                              <1> mget_1: ; 2:
  2145                              <1>         ; eAX (r1) = Physical block number
  2146 000046D0 C3                  <1> 	retn 
  2147                              <1> 		; rts r0
  2148                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2149 000046D1 E88F000000          <1> 	call 	alloc
  2150                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2151                              <1> 	                     ; / block number in r1
  2152                              <1>         ; eAX (r1) = Physical block number
  2153 000046D6 E84A0D0000          <1> 	call 	wslot
  2154                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2155                              <1> 			     ; / first data word in buffer
  2156                              <1>         ; 03/02/2022
  2157 000046DB 31C9                <1> 	xor	ecx, ecx
  2158 000046DD B108                <1> 	mov	cl, 8
  2159                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2160                              <1> 		   ; into new indirect block area for the new
  2161                              <1> 		   ; large file		
  2162 000046DF 89DF                <1> 	mov 	edi, ebx ; r5
  2163 000046E1 BE[FA610000]        <1> 	mov 	esi, i.dskp 
  2164                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2165                              <1> 			   ; / block pointers
  2166                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2167                              <1> 			  ; / large file
  2168                              <1> 	; 22/04/2022
  2169 000046E6 50                  <1> 	push	eax ; * ; bugfix
  2170                              <1> 
  2171                              <1> 	;xor 	ax, ax ; mov ax, 0
  2172                              <1> 	; 03/02/2022
  2173 000046E7 31C0                <1> 	xor	eax, eax
  2174                              <1> mget_3: ;1:
  2175 000046E9 66A5                <1> 	movsw
  2176                              <1> 		; mov (r2),(r5)+
  2177 000046EB 668946FE            <1> 	mov 	[esi-2], ax
  2178                              <1> 		; clr (r2)+
  2179 000046EF E2F8                <1> 	loop	mget_3 ; 1b
  2180                              <1> 		; dec r3
  2181                              <1> 		; bgt 1b
  2182                              <1> 
  2183 000046F1 B1F8                <1> 	mov 	cl, 256-8
  2184                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2185                              <1> mget_4:	; 1
  2186 000046F3 F366AB              <1> 	rep 	stosw
  2187                              <1> 		; clr (r5)+
  2188                              <1> 		; dec r3
  2189                              <1> 		; bgt 1b
  2190                              <1> 	
  2191                              <1> 	; 22/04/2022
  2192                              <1> 	;pop	eax ; * ; bugfix
  2193                              <1> 
  2194                              <1> 	; 24/03/2013
  2195                              <1>         ; AX (r1) = Physical block number
  2196 000046F6 E8370D0000          <1> 	call	dskwr
  2197                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2198                              <1> 
  2199                              <1> 	; 22/04/2022
  2200 000046FB 58                  <1> 	pop	eax ; * ; bugfix
  2201                              <1> 
  2202                              <1>         ; eAX (r1) = Physical block number
  2203 000046FC 66A3[FA610000]      <1> 	mov 	[i.dskp], ax
  2204                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2205                              <1> 	; 03/02/2022
  2206 00004702 800D[F5610000]10    <1> 	or	byte [i.flgs+1], 10h
  2207                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2208                              <1> 		; bis $10000,i.flgs / set large file bit 
  2209                              <1> 				  ; / in i.flgs word of i-node
  2210 00004709 E8F2010000          <1> 	call	setimod
  2211                              <1> 		; jsr r0,setimod / set i-node modified flag
  2212 0000470E E97AFFFFFF          <1>         jmp     mget_0 
  2213                              <1> 		; br mget
  2214                              <1> 
  2215                              <1> mget_5:  ; 4 ; large file
  2216                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2217                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2218                              <1> 			    ; / in indirect block
  2219                              <1> 		; mov r2,-(sp) / save on stack (*)
  2220                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2221                              <1>        		          ; / indirect block
  2222                              <1> 		; bic $!16,r2
  2223 00004713 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2224 00004716 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2225                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2226                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2227                              <1> 	; There is always 1 indirect block for this file system
  2228                              <1> 	; 03/02/2022
  2229 00004717 66A1[FA610000]      <1> 	mov	ax, [i.dskp]
  2230                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2231                              <1> 		; mov i.dskp(r2),r1
  2232                              <1> 	; 03/02/2022
  2233 0000471D 09C0                <1> 	or	eax, eax
  2234                              <1> 	;or 	ax, ax ; R1
  2235 0000471F 7515                <1> 	jnz 	short mget_6 ; 2f
  2236                              <1> 		; bne 2f / if no indirect block exists
  2237 00004721 E83F000000          <1> 	call 	alloc
  2238                              <1> 		; jsr r0,alloc / allocate a new block
  2239 00004726 66A3[FA610000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2240                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2241 0000472C E8CF010000          <1> 	call 	setimod
  2242                              <1> 		; jsr r0,setimod / set i-node modified byte
  2243                              <1> 	; eAX = new block number
  2244 00004731 E85CFEFFFF          <1> 	call 	clear
  2245                              <1> 		; jsr r0,clear / clear new block
  2246                              <1> mget_6: ;2
  2247                              <1> 	; 05/03/2013
  2248                              <1> 	; eAX = r1, physical block number (of indirect block)
  2249 00004736 E8860C0000          <1> 	call 	dskrd ; read indirect block
  2250                              <1> 		; jsr r0,dskrd / read in indirect block
  2251 0000473B 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2252                              <1> 		; mov (sp)+,r2 / get offset
  2253                              <1> 	; eAX = r1, physical block number (of indirect block)
  2254 0000473C 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2255                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2256                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2257 0000473D 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2258                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2259                              <1> 	                  ; / points to location of inter
  2260                              <1> 	; 03/02/2022
  2261 0000473F 668B03              <1> 	mov	ax, [ebx]
  2262                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2263                              <1> 			      ; in file sought in R1 (AX)
  2264                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2265                              <1> 	               	    ; / sought in r1
  2266                              <1> 	; 03/02/2022
  2267 00004742 09C0                <1> 	or	eax, eax
  2268                              <1> 	;or 	ax, ax
  2269 00004744 751D                <1>         jnz 	short mget_7 ; 2f
  2270                              <1> 		; bne 2f / if no block exists 
  2271 00004746 E81A000000          <1> 	call 	alloc
  2272                              <1> 		; jsr r0,alloc / allocate a new block
  2273 0000474B 668903              <1> 	mov 	[ebx], ax ; R1
  2274                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2275                              <1> 	                    ; / indirect block
  2276 0000474E 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2277                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2278 0000474F 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2279 00004750 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2280 00004751 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2281                              <1> 		; mov (r2),-(sp) / save block number of new block
  2282                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2283 00004753 E8CD0C0000          <1> 	call 	wslot
  2284                              <1> 		; jsr r0,wslot
  2285                              <1>         ; eAX (r1) = physical block number
  2286                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2287 00004758 E8D50C0000          <1> 	call 	dskwr
  2288                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2289                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2290                              <1> 			     ; / back out on disk
  2291 0000475D 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2292                              <1> 		; mov (sp),r1 / restore block number of new block	
  2293                              <1> 	; eAX (r1) = physical block number of new block
  2294 0000475E E82FFEFFFF          <1> 	call 	clear
  2295                              <1> 		; jsr r0,clear / clear new block	
  2296                              <1> mget_7: ; 2
  2297 00004763 5A                  <1> 	pop 	edx ; **
  2298                              <1> 		; tst (sp)+ / bump stack pointer
  2299                              <1> 	; eAX (r1) = Block number of new block
  2300 00004764 C3                  <1> 	retn
  2301                              <1> 		; rts r0
  2302                              <1> 
  2303                              <1> alloc:
  2304                              <1> 	; 03/02/2022
  2305                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2306                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2307                              <1> 	;
  2308                              <1> 	; get a free block and 
  2309                              <1> 	; set the corresponding bit in the free storage map
  2310                              <1> 	; 
  2311                              <1> 	; INPUTS ->
  2312                              <1> 	;    cdev (current device)
  2313                              <1> 	;    r2 
  2314                              <1> 	;    r3
  2315                              <1> 	; OUTPUTS ->
  2316                              <1> 	;    r1 (physical block number of block assigned)
  2317                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2318                              <1> 	;
  2319                              <1> 	; ((AX = R1)) output
  2320                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2321                              <1>         ;    ((Modified registers: DX, CX))  
  2322                              <1> 
  2323                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2324                              <1> 		;mov r3,-(sp)
  2325                              <1> 	;push 	ecx
  2326 00004765 53                  <1> 	push 	ebx ; R2
  2327                              <1> 	;push 	edx ; R3
  2328 00004766 BB[C8750000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2329                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2330 0000476B 803D[E4640000]00    <1> 	cmp 	byte [cdev], 0
  2331                              <1> 		; tst cdev
  2332 00004772 7605                <1> 	jna	short alloc_1
  2333                              <1> 		; beq 1f / drum is device
  2334 00004774 BB[D0770000]        <1> 	mov	ebx, mount
  2335                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2336                              <1> 			      ; / free storage map
  2337                              <1> alloc_1: ; 1
  2338                              <1> 	; 03/02/2022
  2339                              <1> 	;sub	ecx, ecx
  2340                              <1> 	;sub	edx, edx
  2341                              <1> 	;sub	eax, eax
  2342                              <1> 
  2343 00004779 668B0B              <1>         mov	cx, [ebx]
  2344                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2345                              <1> 			     ; / storage map
  2346                              <1> 	; 03/02/2022
  2347 0000477C C1E103              <1> 	shl	ecx, 3
  2348                              <1> 	;shl	cx, 3
  2349                              <1> 		; asl r1 / multiply r1 by eight gives 
  2350                              <1> 		; number of blocks in device
  2351                              <1> 		; asl r1
  2352                              <1> 		; asl r1
  2353                              <1> 	;;push	cx ;; 01/08/2013
  2354                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2355 0000477F 31C0                <1> 	xor 	eax, eax ; 0
  2356                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2357                              <1> alloc_2: ; 1
  2358 00004781 43                  <1> 	inc 	ebx ; 18/8/2012
  2359 00004782 43                  <1> 	inc 	ebx ; 
  2360 00004783 668B13              <1> 	mov 	dx, [ebx]
  2361                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2362                              <1> 	; 03/02/2022
  2363 00004786 09D2                <1> 	or	edx, edx
  2364                              <1> 	;or 	dx, dx
  2365 00004788 750D                <1> 	jnz 	short alloc_3 ; 1f
  2366                              <1> 		; bne 1f / branch if any free blocks in this word	
  2367 0000478A 6683C010            <1> 	add 	ax, 16
  2368                              <1> 		; add $16.,r1
  2369                              <1> 	; 03/02/2022
  2370 0000478E 39C8                <1> 	cmp	eax, ecx
  2371                              <1> 	;cmp 	ax, cx    
  2372                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2373 00004790 72EF                <1> 	jb 	short alloc_2
  2374                              <1> 		; blo 1b
  2375                              <1> 	; 14/11/2015
  2376                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2377                              <1> 	;	because of a (DMA or another) r/w error, 
  2378                              <1> 	;	we will be here, at 'jmp panic' code address,
  2379                              <1> 	;	even if the (disk) file system space is not full !!!
  2380                              <1> 	;	(cx = 0)	
  2381                              <1> 	;
  2382 00004792 E90CE2FFFF          <1> 	jmp     panic 
  2383                              <1> 		; jmp panic / found no free storage
  2384                              <1> alloc_3: ; 1
  2385                              <1> 	; 03/02/2022
  2386 00004797 D1EA                <1> 	shr	edx, 1
  2387                              <1> 	;shr	dx, 1
  2388                              <1> 		; asr r3 / find a free block
  2389 00004799 7203                <1> 	jc	short alloc_4 ; 1f
  2390                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2391                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2392                              <1> 	; 03/02/2022
  2393 0000479B 40                  <1> 	inc	eax
  2394                              <1> 	;inc	ax
  2395                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2396 0000479C EBF9                <1> 	jmp 	short alloc_3
  2397                              <1> 		; br 1b
  2398                              <1> alloc_4: ; 1:
  2399                              <1> 	;; pop cx ;; 01/08/2013
  2400                              <1> 		; tst (sp)+ / bump sp
  2401                              <1> 	; 02/04/2013 
  2402 0000479E E829000000          <1> 	call	free3
  2403                              <1> 		; jsr r0,3f / have found a free block
  2404                              <1> 	; 21/8/2012
  2405 000047A3 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2406 000047A6 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2407                              <1> 		; bic r3,(r2) / set bit for this block 
  2408                              <1> 		            ; / i.e. assign block
  2409                              <1> 		; br 2f
  2410 000047A9 EB09                <1> 	jmp 	short alloc_5
  2411                              <1> 
  2412                              <1> free:
  2413                              <1> 	; 03/02/2022
  2414                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2415                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2416                              <1> 	;
  2417                              <1> 	; calculates byte address and bit position for given block number
  2418                              <1> 	; then sets the corresponding bit in the free storage map
  2419                              <1> 	; 
  2420                              <1> 	; INPUTS ->
  2421                              <1> 	;    r1 - block number for a block structured device
  2422                              <1> 	;    cdev - current device 
  2423                              <1> 	; OUTPUTS ->
  2424                              <1> 	;    free storage map is updated
  2425                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2426                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2427                              <1> 	;
  2428                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2429                              <1>         ;  ((Modified registers: DX, CX))  
  2430                              <1> 
  2431                              <1> 		;mov r2,-(sp) / save r2, r3
  2432                              <1> 		;mov r3,-(sp)
  2433                              <1> 	;push 	ecx
  2434 000047AB 53                  <1> 	push 	ebx ; R2
  2435                              <1> 	;push 	edx ; R3 
  2436                              <1> 
  2437 000047AC E81B000000          <1>         call    free3
  2438                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2439                              <1> 				 ; / in free storage map for block
  2440 000047B1 660913              <1> 	or 	[ebx], dx  
  2441                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2442                              <1> 			    ;  / indicates free block	
  2443                              <1> 	; 0 -> allocated, 1 -> free
  2444                              <1> 
  2445                              <1> alloc_5:
  2446                              <1> 	; 07/04/2013
  2447                              <1> free_1: ; 2:
  2448                              <1> 	;pop 	edx
  2449                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2450 000047B4 5B                  <1> 	pop	ebx
  2451                              <1> 		; mov (sp)+,r2
  2452                              <1> 	; pop	ecx
  2453 000047B5 803D[E4640000]00    <1> 	cmp 	byte [cdev], 0
  2454                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2455                              <1> 			 ; / cdev = 1, mountable device
  2456 000047BC 7707                <1> 	ja	short alloc_6 ; 1f
  2457                              <1> 		; bne 1f
  2458                              <1> 	;mov	byte [smod], 1
  2459 000047BE FE05[F3640000]      <1> 	inc 	byte [smod]
  2460                              <1> 		; incb smod / set super block modified for drum
  2461                              <1> 	; eAX (r1) = block number
  2462 000047C4 C3                  <1> 	retn
  2463                              <1> 		; rts r0
  2464                              <1> free_2:
  2465                              <1> alloc_6: ; 1:
  2466                              <1> 	;mov 	byte [mmod], 1
  2467 000047C5 FE05[F4640000]      <1> 	inc 	byte [mmod]
  2468                              <1> 		; incb	mmod 
  2469                              <1> 		  ; / set super block modified for mountable device
  2470                              <1> 	; eAX (r1) = block number
  2471 000047CB C3                  <1> 	retn	
  2472                              <1> 		; rts r0
  2473                              <1> free3:
  2474                              <1> 	; 03/02/2022
  2475                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2476                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2477                              <1> 	;
  2478                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2479                              <1> 	; 
  2480                              <1> alloc_free_3: ; 3
  2481                              <1> 	;mov 	dx, 1
  2482                              <1> 	; 03/02/2022
  2483 000047CC 31D2                <1> 	xor	edx, edx
  2484 000047CE 42                  <1> 	inc	edx
  2485                              <1> 	; edx = 1
  2486 000047CF 88C1                <1> 	mov 	cl, al
  2487                              <1> 		; mov r1,r2 / block number, k, = 1		
  2488 000047D1 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2489                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2490 000047D4 7402                <1> 	jz 	short free4
  2491                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2492                              <1> 			       ; / (k) mod 8
  2493                              <1> 	;shl 	dx, cl
  2494                              <1> 	; 03/02/2022
  2495 000047D6 D3E2                <1> 	shl	edx, cl
  2496                              <1> free4:
  2497 000047D8 0FB7D8              <1> 	movzx 	ebx, ax
  2498                              <1> 		; mov r1,r2 / divide block number by 16
  2499                              <1> 	; 03/02/2022
  2500 000047DB C1EB04              <1> 	shr	ebx, 4
  2501                              <1> 	;shr 	bx, 4
  2502                              <1> 		; asr r2
  2503                              <1> 		; asr r2
  2504                              <1> 		; asr r2
  2505                              <1> 		; asr r2
  2506                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2507                              <1> 		       ; / bit for block is in lower half of word
  2508                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2509                              <1> 		        ; / storage map
  2510                              <1> alloc_free_4: ; 1
  2511                              <1> 	; 03/02/2022
  2512 000047DE D1E3                <1> 	shl	ebx, 1
  2513                              <1> 	;shl 	bx, 1
  2514                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2515 000047E0 81C3[CA750000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2516                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2517                              <1> 	    		        ; / with block bit in it 	
  2518 000047E6 803D[E4640000]00    <1> 	cmp	byte [cdev], 0
  2519                              <1> 		; tst cdev
  2520 000047ED 7606                <1> 	jna	short alloc_free_5
  2521                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2522 000047EF 81C308020000        <1> 	add	ebx, mount - systm
  2523                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2524                              <1> 				    ; / mountable device with bit of block to be
  2525                              <1> 				    ; / freed
  2526                              <1> alloc_free_5: ; 1 
  2527 000047F5 C3                  <1> 	retn
  2528                              <1> 		; rts r0 / return to 'free'
  2529                              <1> 	      ; 2
  2530                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2531                              <1> 	
  2532                              <1> iget:
  2533                              <1> 	; 03/02/2022
  2534                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2535                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2536                              <1> 	;
  2537                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2538                              <1> 	;
  2539                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2540                              <1> 	; 
  2541                              <1> 	; INPUTS ->
  2542                              <1> 	;    ii - current i-number, rootdir
  2543                              <1> 	;    cdev - new i-node device
  2544                              <1> 	;    idev - current i-node device
  2545                              <1> 	;    imod - current i-node modified flag
  2546                              <1> 	;    mnti - cross device file i-number
  2547                              <1> 	;    r1 - i-numbe rof new i-node
  2548                              <1> 	;    mntd - mountable device number		
  2549                              <1> 	; 	 
  2550                              <1> 	; OUTPUTS ->
  2551                              <1> 	;    cdev, idev, imod, ii, r1
  2552                              <1> 	;
  2553                              <1> 	; ((AX = R1)) input/output
  2554                              <1> 	;
  2555                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2556                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2557                              <1> 
  2558 000047F6 8A15[E4640000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2559 000047FC 8A35[E2640000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2560                              <1> 	;
  2561 00004802 663B05[E0640000]    <1> 	cmp 	ax, [ii]
  2562                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2563 00004809 7504                <1> 	jne 	short iget_1
  2564                              <1> 		; bne 1f
  2565 0000480B 38F2                <1> 	cmp	dl, dh
  2566                              <1> 		; cmp idev,cdev
  2567                              <1> 			  ; / is device number of i-node = current device
  2568 0000480D 7472                <1>         je      short iget_5
  2569                              <1> 		; beq 2f
  2570                              <1> iget_1: ; 1:
  2571 0000480F 30DB                <1> 	xor	bl, bl
  2572 00004811 381D[F2640000]      <1> 	cmp	[imod], bl ; 0	
  2573                              <1> 		; tstb imod / has i-node of current file
  2574                              <1> 			  ; / been modified i.e., imod set
  2575 00004817 7629                <1> 	jna	short iget_2
  2576                              <1> 		; beq 1f
  2577 00004819 881D[F2640000]      <1> 	mov	[imod], bl ; 0
  2578                              <1> 		;  clrb	imod / if it has, 
  2579                              <1> 			   ; / we must write the new i-node out on disk
  2580                              <1> 	; 03/02/2022
  2581 0000481F 50                  <1> 	push	eax ; *
  2582                              <1> 	;push	ax
  2583                              <1> 		; mov r1,-(sp)
  2584                              <1> 	;mov	dl, [cdev]
  2585 00004820 52                  <1> 	push	edx ; **
  2586                              <1> 	;push	dx
  2587                              <1> 		; mov cdev,-(sp)
  2588 00004821 66A1[E0640000]      <1> 	mov	ax, [ii]
  2589                              <1> 		; mov ii,r1
  2590                              <1> 	;mov	dh, [idev]
  2591 00004827 8835[E4640000]      <1> 	mov	[cdev], dh
  2592                              <1> 		; mov idev,cdev
  2593 0000482D FEC3                <1> 	inc	bl ; 1
  2594                              <1> 	; 31/07/2013
  2595 0000482F 881D[7C650000]      <1> 	mov     [rw], bl ; 1 == write 
  2596                              <1> 	;;28/07/2013 rw -> u.rw
  2597                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2598 00004835 E848000000          <1> 	call	icalc
  2599                              <1> 		; jsr r0,icalc; 1
  2600                              <1> 	;pop	dx
  2601                              <1> 	; 03/02/2022
  2602 0000483A 5A                  <1> 	pop	edx ; **
  2603 0000483B 8815[E4640000]      <1> 	mov	[cdev], dl
  2604                              <1> 		; mov (sp)+,cdev
  2605                              <1> 	; 03/02/2022
  2606 00004841 58                  <1> 	pop	eax ; *
  2607                              <1> 	;pop	ax
  2608                              <1> 		; mov (sp)+,r1
  2609                              <1> iget_2: ; 1:
  2610 00004842 6621C0              <1> 	and	ax, ax
  2611                              <1> 		; tst r1 / is new i-number non zero
  2612 00004845 7434                <1> 	jz	short iget_4 ; 2f
  2613                              <1> 		; beq 2f / branch if r1=0
  2614                              <1> 
  2615                              <1> 	;mov 	dl, [cdev]
  2616 00004847 08D2                <1> 	or	dl, dl
  2617                              <1> 		; tst cdev / is the current device number non zero
  2618                              <1> 			 ; / (i.e., device =/ drum)
  2619 00004849 7517                <1> 	jnz	short iget_3 ;  1f
  2620                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2621 0000484B 663B05[E8640000]    <1> 	cmp	ax, [mnti]			
  2622                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2623                              <1> 			    ; / file (root directory of mounted device)
  2624 00004852 750E                <1> 	jne	short iget_3 ; 1f
  2625                              <1> 		; bne 1f
  2626                              <1>         ;mov    bl, [mntd]
  2627 00004854 FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2628 00004856 8815[E4640000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2629                              <1> 		; mov mntd,cdev / make mounted device the current device
  2630 0000485C 66A1[EE640000]      <1> 	mov	ax, [rootdir]
  2631                              <1> 		; mov rootdir,r1
  2632                              <1> iget_3: ; 1:
  2633 00004862 66A3[E0640000]      <1> 	mov	[ii], ax
  2634                              <1> 		; mov r1,ii
  2635 00004868 8815[E2640000]      <1> 	mov	[idev], dl ; cdev
  2636                              <1> 		; mov cdev,idev
  2637 0000486E 30DB                <1> 	xor	bl, bl
  2638                              <1>         ; 31/07/2013
  2639 00004870 881D[7C650000]      <1> 	mov     [rw], bl ; 0 == read 
  2640                              <1> 	;;28/07/2013 rw -> u.rw       
  2641                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2642 00004876 E807000000          <1> 	call	icalc
  2643                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2644                              <1> iget_4: ; 2:
  2645 0000487B 66A1[E0640000]      <1> 	mov	ax, [ii]
  2646                              <1> 		; mov ii,r1
  2647                              <1> iget_5:
  2648 00004881 C3                  <1> 	retn
  2649                              <1> 		; rts r0
  2650                              <1> 
  2651                              <1> icalc:
  2652                              <1> 	; 04/04/2022 (47->31)
  2653                              <1> 	;	(Inode Table/List Address modification)
  2654                              <1> 	; 03/02/2022
  2655                              <1> 	; 02/07/2015
  2656                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2657                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2658                              <1> 	;
  2659                              <1> 	; calculate physical block number from i-number then
  2660                              <1> 	; read or write that block
  2661                              <1> 	;
  2662                              <1> 	; 'icalc' is called from 'iget'
  2663                              <1> 	;
  2664                              <1> 	; for original unix v1:
  2665                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2666                              <1>        	; / (i+31.) mod 16. bytes from its start
  2667                              <1> 	;
  2668                              <1> 	; for retro unix 8086 v1:
  2669                              <1> 	;  i-node is located in block (i+47)/16 and
  2670                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2671                              <1> 	;
  2672                              <1> 	; INPUTS ->
  2673                              <1> 	;    r1 - i-number of i-node
  2674                              <1> 	; 	 
  2675                              <1> 	; OUTPUTS ->
  2676                              <1> 	;    inode r/w
  2677                              <1> 	;
  2678                              <1> 	; ((AX = R1)) input
  2679                              <1> 	;
  2680                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2681                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2682                              <1> 	;
  2683 00004882 0FB7D0              <1> 	movzx	edx, ax	
  2684                              <1> 	;add	dx, 47
  2685                              <1> 	; 04/04/2022
  2686 00004885 6683C21F            <1> 	add	dx, 31
  2687 00004889 89D0                <1> 	mov	eax, edx
  2688                              <1> 	;;add	ax, 47	; add 47 to inode number
  2689                              <1> 	;add	ax, 31
  2690                              <1> 		; add $31.,r1 / add 31. to i-number
  2691 0000488B 50                  <1> 	push	eax
  2692                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2693                              <1> 	; 03/02/2022
  2694 0000488C C1E804              <1> 	shr	eax, 4
  2695                              <1> 	;shr 	ax, 4
  2696                              <1> 		; asr r1 / divide by 16.
  2697                              <1> 		; asr r1
  2698                              <1> 		; asr r1
  2699                              <1> 		; asr r1 / r1 contains block number of block
  2700                              <1> 		       ; / in which i-node exists
  2701 0000488F E82D0B0000          <1> 	call	dskrd
  2702                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2703                              <1> 	; 31/07/2013
  2704 00004894 803D[7C650000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2705                              <1> 	;; 28/07/2013 rw -> u.rw
  2706                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2707                              <1> 		; tst (r0)
  2708 0000489B 7605                <1> 	jna	short icalc_1
  2709                              <1> 		; beq 1f / branch to wslot when argument
  2710                              <1> 		       ; / in icalc call = 1
  2711                              <1> 	; eAX = r1 = block number
  2712 0000489D E8830B0000          <1> 	call	wslot
  2713                              <1> 		; jsr r0,wslot / set up data buffer for write
  2714                              <1> 			     ; / (will be same buffer as dskrd got)
  2715                              <1> 	; eBX = r5 points to first word in data area for this block
  2716                              <1> icalc_1: ; 1:
  2717 000048A2 5A                  <1> 	pop	edx 
  2718 000048A3 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2719                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2720                              <1> 			      ; / gives (i+31.) mod 16
  2721 000048A6 C1E205              <1> 	shl 	edx, 5
  2722                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2723 000048A9 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2724 000048AB 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2725                              <1>           	; eSI (r5) points to first word in i-node i.	
  2726                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2727                              <1> 			     ; / 32.*(i+31.)mod16
  2728                              <1> 		; mov $5,lsh / for i-node i.
  2729                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2730 000048AD BF[F4610000]        <1> 	mov	edi, inode
  2731                              <1> 		; mov $inode,r1 / inode is address of first word 
  2732                              <1> 			      ; / of current i-node
  2733                              <1> 	; 03/02/2022
  2734 000048B2 29C9                <1> 	sub	ecx, ecx
  2735 000048B4 B108                <1> 	mov	cl, 8 
  2736                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2737                              <1> 		; mov $16.,r3
  2738                              <1>         ; 31/07/2013
  2739 000048B6 382D[7C650000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2740                              <1>        ;;28/07/2013 rw -> u.rw                 
  2741                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2742                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2743 000048BC 7609                <1> 	jna	short icalc_3
  2744                              <1> 		; beq 2f / r0 now contains proper return address 
  2745                              <1> 		       ; / for rts r0
  2746                              <1> icalc_2: ; 1:
  2747 000048BE 87F7                <1> 	xchg 	esi, edi
  2748                              <1> 	; overwrite old i-node (in buffer to be written)
  2749 000048C0 F3A5                <1> 	rep 	movsd
  2750                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2751                              <1> 		; dec r3
  2752                              <1> 		; bgt 1b
  2753                              <1> 	;call	dskwr
  2754                              <1> 		; jsr r0,dskwr / write inode out on device
  2755                              <1> 	;retn
  2756                              <1> 		; rts r0
  2757                              <1> 	; 03/02/2022
  2758 000048C2 E96B0B0000          <1> 	jmp	dskwr
  2759                              <1> icalc_3: ; 2:
  2760                              <1> 	; copy new i-node into inode area of (core) memory
  2761 000048C7 F3A5                <1> 	rep 	movsd
  2762                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2763                              <1> 		                ; / "inode" area of core
  2764                              <1> 		; dec r3
  2765                              <1> 		; bgt 2b
  2766 000048C9 C3                  <1> 	retn
  2767                              <1> 		; rts r0
  2768                              <1> 
  2769                              <1> access:
  2770                              <1> 	; 03/02/2022
  2771                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2772                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2773                              <1> 	;
  2774                              <1> 	; check whether user is owner of file or user has read or write
  2775                              <1> 	; permission (based on i.flgs).
  2776                              <1> 	;
  2777                              <1> 	; INPUTS ->
  2778                              <1> 	;    r1 - i-number of file
  2779                              <1> 	;    u.uid
  2780                              <1> 	; arg0 -> (owner flag mask)	 		
  2781                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2782                              <1> 	; OUTPUTS ->
  2783                              <1> 	;    inode (or jump to error)
  2784                              <1> 	;
  2785                              <1> 	; ((AX = R1)) input/output
  2786                              <1> 	;
  2787                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2788                              <1> 	;
  2789                              <1> 
  2790                              <1> 	;push	dx  ; save flags (DL)
  2791                              <1> 	; 03/02/2022
  2792 000048CA 52                  <1> 	push	edx ; save flags (DL)
  2793 000048CB E826FFFFFF          <1> 	call	iget
  2794                              <1> 		; jsr r0,iget / read in i-node for current directory
  2795                              <1> 			    ; / (i-number passed in r1)
  2796 000048D0 8A0D[F4610000]      <1> 	mov	cl, [i.flgs]
  2797                              <1> 		; mov i.flgs,r2
  2798                              <1> 	; 03/02/2022
  2799 000048D6 5A                  <1> 	pop	edx ; restore flags (DL)
  2800                              <1> 	;pop	dx  ; restore flags (DL)
  2801 000048D7 8A35[46650000]      <1> 	mov	dh, [u.uid]
  2802 000048DD 3A35[F7610000]      <1> 	cmp	dh, [i.uid]
  2803                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2804 000048E3 7503                <1> 	jne	short access_1
  2805                              <1> 		; bne 1f / no, then branch
  2806 000048E5 C0E902              <1> 	shr	cl, 2
  2807                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2808                              <1> 		        ; / read/write bits
  2809                              <1> 		; asrb r2
  2810                              <1> access_1: ; 1:
  2811 000048E8 20D1                <1> 	and	cl, dl
  2812                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2813                              <1> 			     ; / in access call
  2814 000048EA 7513                <1> 	jnz	short access_2
  2815                              <1> 		; bne 1f
  2816 000048EC 08F6                <1> 	or	dh, dh	; super user  (root) ?
  2817                              <1> 		; tstb u.uid
  2818 000048EE 740F                <1> 	jz	short access_2 ; yes, super user
  2819                              <1> 	;jnz	error
  2820                              <1> 		; beq 1f
  2821                              <1> 		; jmp error
  2822 000048F0 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2822 000048F8 0000                <1>
  2823                              <1> 			; 'permission denied !' error
  2824 000048FA E9E2E7FFFF          <1> 	jmp	error
  2825                              <1> 
  2826                              <1> access_2: ; 1:
  2827                              <1> 	; DL = flags
  2828 000048FF C3                  <1> 	retn
  2829                              <1> 		; rts r0
  2830                              <1> 
  2831                              <1> setimod:
  2832                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2833                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2834                              <1> 	;
  2835                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2836                              <1> 	; the inode has been modified. Also puts the time of modification
  2837                              <1> 	; into the inode.
  2838                              <1> 	;
  2839                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2840                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  2841                              <1> 	;
  2842                              <1> 	
  2843                              <1> 	; push 	edx
  2844 00004900 50                  <1> 	push	eax
  2845                              <1> 
  2846 00004901 C605[F2640000]01    <1> 	mov 	byte [imod], 1
  2847                              <1> 		; movb $1,imod / set current i-node modified bytes
  2848                              <1> 	; Erdogan Tan 14-7-2012
  2849 00004908 E825E3FFFF          <1> 	call 	epoch
  2850                              <1> 		 ; mov s.time,i.mtim 
  2851                              <1> 			    ; / put present time into file modified time
  2852                              <1> 		 ; mov s.time+2,i.mtim+2
  2853                              <1> 
  2854 0000490D A3[0E620000]        <1> 	mov 	[i.mtim], eax
  2855                              <1> 	
  2856                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2857                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2858 00004912 833D[0A620000]00    <1> 	cmp	dword [i.ctim], 0
  2859 00004919 7505                <1> 	jnz	short setimod_ok
  2860                              <1> 
  2861 0000491B A3[0A620000]        <1> 	mov 	[i.ctim], eax
  2862                              <1> 
  2863                              <1> setimod_ok: ; 31/07/2013
  2864 00004920 58                  <1> 	pop	eax
  2865                              <1> 	;pop	edx
  2866                              <1> 	
  2867 00004921 C3                  <1> 	retn
  2868                              <1> 		; rts r0
  2869                              <1> 
  2870                              <1> itrunc:
  2871                              <1> 	; 03/02/2022
  2872                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2873                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2874                              <1> 	;
  2875                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2876                              <1> 	;  to zero length.
  2877                              <1> 	;
  2878                              <1> 	; INPUTS ->
  2879                              <1> 	;    r1 - i-number of i-node
  2880                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2881                              <1> 	;    i.flgs - large file flag		
  2882                              <1> 	;    i.size - size of file	
  2883                              <1> 	; 	 
  2884                              <1> 	; OUTPUTS ->
  2885                              <1> 	;    i.flgs - large file flag is cleared
  2886                              <1> 	;    i.size - set to 0	
  2887                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2888                              <1> 	;    setimod - set to indicate i-node has been modified
  2889                              <1> 	;    r1 - i-number of i-node  					
  2890                              <1> 	;
  2891                              <1> 	; ((AX = R1)) input/output
  2892                              <1> 	;
  2893                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2894                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2895                              <1> 
  2896 00004922 E8CFFEFFFF          <1> 	call	iget
  2897                              <1> 		; jsr r0,iget
  2898 00004927 BE[FA610000]        <1> 	mov	esi, i.dskp
  2899                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2900 0000492C 31C0                <1> 	xor	eax, eax
  2901                              <1> itrunc_1: ; 1:
  2902 0000492E 66AD                <1> 	lodsw
  2903                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2904                              <1> 	; 03/02/2022
  2905 00004930 09C0                <1> 	or	eax, eax
  2906                              <1> 	;or 	ax, ax
  2907 00004932 7433                <1> 	jz	short itrunc_5
  2908                              <1> 		; beq 5f
  2909 00004934 56                  <1> 	push	esi
  2910                              <1> 		; mov r2,-(sp)
  2911                              <1> 	; 03/02/2022
  2912 00004935 F605[F5610000]10    <1> 	test	byte [i.flgs+1], 10h
  2913                              <1> 	;test	word [i.flgs], 1000h
  2914                              <1> 		; bit $10000,i.flgs / test large file bit?
  2915 0000493C 7423                <1> 	jz	short itrunc_4
  2916                              <1> 		; beq 4f / if clear, branch
  2917 0000493E 50                  <1> 	push	eax
  2918                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2919 0000493F E87D0A0000          <1> 	call	dskrd
  2920                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2921                              <1> 			     ; / pointed to by r5
  2922                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2923                              <1> 	; 03/02/2022
  2924 00004944 31C9                <1> 	xor	ecx, ecx
  2925 00004946 FEC5                <1> 	inc	ch ; mov ch, 1
  2926                              <1> 	; ecx = 256
  2927                              <1> 	;mov	ecx, 256
  2928                              <1> 		; mov $256.,r3 / move word count into r3
  2929 00004948 89DE                <1> 	mov	esi, ebx
  2930                              <1> itrunc_2: ; 2:
  2931 0000494A 66AD                <1> 	lodsw
  2932                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2933                              <1> 			     ; / physical block number
  2934                              <1> 	; 03/02/2022
  2935 0000494C 21C0                <1> 	and	eax, eax
  2936                              <1> 	;and	ax, ax
  2937 0000494E 7407                <1> 	jz	short itrunc_3
  2938                              <1> 		; beq 3f / branch if zero
  2939                              <1> 	; 03/02/2022
  2940 00004950 51                  <1> 	push	ecx
  2941                              <1> 	;push	cx
  2942                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2943                              <1> 	;push	esi
  2944                              <1> 		; mov r5,-(sp)
  2945 00004951 E855FEFFFF          <1> 	call	free
  2946                              <1> 		; jsr r0,free / free block in free storage map
  2947                              <1> 	;pop	esi
  2948                              <1> 		; mov(sp)+,r5
  2949                              <1> 	;pop	cx
  2950 00004956 59                  <1> 	pop	ecx
  2951                              <1> 		; mov (sp)+,r3
  2952                              <1> itrunc_3: ; 3:
  2953 00004957 E2F1                <1> 	loop	itrunc_2
  2954                              <1> 		; dec r3 / decrement word count
  2955                              <1> 		; bgt 2b / branch if positive
  2956 00004959 58                  <1> 	pop	eax
  2957                              <1> 		; mov (sp)+,r1 / put physical block number of 
  2958                              <1> 			     ; / indirect block
  2959                              <1> 	; 01/08/2013
  2960                              <1>         ;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2961                              <1> 	; 03/02/2022
  2962 0000495A 8025[F5610000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  2963                              <1> itrunc_4: ; 4:
  2964 00004961 E845FEFFFF          <1> 	call	free
  2965                              <1> 		; jsr r0,free / free indirect block
  2966 00004966 5E                  <1> 	pop	esi
  2967                              <1> 		; mov (sp)+,r2
  2968                              <1> itrunc_5: ; 5:
  2969 00004967 81FE[0A620000]      <1> 	cmp	esi, i.dskp+16
  2970                              <1> 		; cmp r2,$i.dskp+16.
  2971 0000496D 72BF                <1> 	jb	short itrunc_1	
  2972                              <1> 		; bne 1b / branch until all i.dskp entries check
  2973                              <1> 	; 03/02/2022
  2974                              <1> 	;and	byte [i.flgs+1], 0EFh
  2975                              <1> 	; 01/08/2013
  2976                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2977                              <1> 		; bic $10000,i.flgs / clear large file bit
  2978 0000496F BF[FA610000]        <1> 	mov	edi, i.dskp
  2979                              <1> 	;mov	cx, 8
  2980                              <1> 	;xor 	ax, ax
  2981                              <1> 	; 03/02/2022
  2982 00004974 29C9                <1> 	sub	ecx, ecx
  2983 00004976 B108                <1> 	mov	cl, 8
  2984 00004978 29C0                <1> 	sub	eax, eax
  2985 0000497A 66A3[F8610000]      <1> 	mov	[i.size], ax ; 0
  2986                              <1> 		; clr i.size / zero file size
  2987 00004980 F366AB              <1> 	rep	stosw
  2988                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  2989                              <1> 			   ; / zero block pointers
  2990 00004983 E878FFFFFF          <1> 	call	setimod
  2991                              <1> 		; jsr r0,setimod / set i-node modified flag
  2992 00004988 66A1[E0640000]      <1> 	mov	ax, [ii]
  2993                              <1> 		; mov ii,r1
  2994 0000498E C3                  <1> 	retn
  2995                              <1> 		; rts r0
  2996                              <1> 
  2997                              <1> imap:
  2998                              <1> 	; 12/02/2022
  2999                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3000                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3001                              <1> 	;
  3002                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3003                              <1> 	; allocation bit for an i-node whose number in r1.
  3004                              <1> 	;
  3005                              <1> 	; INPUTS ->
  3006                              <1> 	;    r1 - contains an i-number
  3007                              <1> 	;    fsp - start of table containing open files
  3008                              <1> 	;
  3009                              <1> 	; OUTPUTS ->
  3010                              <1> 	;    r2 - byte address of byte with the allocation bit
  3011                              <1> 	;    mq - a mask to locate the bit position.	
  3012                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3013                              <1> 	;
  3014                              <1> 	; ((AX = R1)) input/output
  3015                              <1> 	; ((DL/DX = MQ)) output
  3016                              <1> 	; ((BX = R2)) output
  3017                              <1> 	;
  3018                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3019                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3020                              <1> 	;
  3021                              <1> 		; / get the byte that has the allocation bit for 
  3022                              <1> 		; / the i-number contained in r1
  3023                              <1> 	;mov	dx, 1
  3024 0000498F B201                <1> 	mov	dl, 1
  3025                              <1> 		; mov $1,mq / put 1 in the mq
  3026 00004991 0FB7D8              <1> 	movzx	ebx, ax
  3027                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3028                              <1>  		          ; / in the map we must find
  3029 00004994 6683EB29            <1> 	sub	bx, 41
  3030                              <1> 		; sub $41.,r2 / r2 has i-41
  3031 00004998 88D9                <1> 	mov	cl, bl
  3032                              <1> 		; mov r2,r3 / r3 has i-41
  3033 0000499A 80E107              <1> 	and	cl, 7
  3034                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3035                              <1> 			   ; / the bit position
  3036 0000499D 7402                <1> 	jz	short imap1
  3037                              <1> 	;shl	dx, cl
  3038 0000499F D2E2                <1> 	shl	dl, cl
  3039                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3040                              <1> imap1:			   ; / to the left to mask the correct bit
  3041                              <1> 	; 03/02/2022
  3042 000049A1 C1EB03              <1> 	shr	ebx, 3
  3043                              <1> 	;shr	bx, 3
  3044                              <1> 		; asr r2
  3045                              <1> 		; asr r2
  3046                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3047                              <1> 		       ; / from the start of the map
  3048                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3049 000049A4 BE[C8750000]        <1> 	mov	esi, systm
  3050                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3051                              <1> 				; / the super block for drum
  3052                              <1> 	;cmp	word [cdev], 0
  3053 000049A9 803D[E4640000]00    <1> 	cmp	byte [cdev], 0
  3054                              <1> 		; tst cdev / is the device the disk
  3055 000049B0 7606                <1> 	jna	short imap2
  3056                              <1> 		; beq 1f / yes
  3057 000049B2 81C608020000        <1> 	add	esi, mount - systm
  3058                              <1> 		; add $mount-systm,r2 / for mounted device,
  3059                              <1> 			; / r2 points to 1st word of its super block
  3060                              <1> imap2: ; 1:
  3061 000049B8 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3062                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3063 000049BB 6683C304            <1> 	add	bx, 4
  3064 000049BF 01F3                <1> 	add	ebx, esi
  3065                              <1>         	; add (sp)+,r2 / ?
  3066                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3067                              <1> 		      ;; (2 + free map size + 2)
  3068                              <1> 		; add $2,r2 / ?
  3069                              <1>  	
  3070                              <1> 	; 12/02/2022
  3071 000049C1 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3072 000049C7 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3073                              <1> 			  ; if inode num overs inode count
  3074                              <1> 
  3075                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3076                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3077                              <1> 
  3078                              <1> 	; 11/02/2022
  3079                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3080                              <1> 	;	(number of requested inode > inode count)
  3081                              <1> 
  3082 000049C9 C3                  <1> 	retn
  3083                              <1> 		; rts r0
  2057                                  %include 'u6.s'        ; 31/05/2015
  2058                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS6.INC
  2059                              <1> ; Last Modification: 19/07/2022
  2060                              <1> ; ----------------------------------------------------------------------------
  2061                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2062                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2063                              <1> ;
  2064                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2065                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2066                              <1> ; <Bell Laboratories (17/3/1972)>
  2067                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2068                              <1> ;
  2069                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2070                              <1> ;
  2071                              <1> ; ****************************************************************************
  2072                              <1> ; 18/11/2015
  2073                              <1> 
  2074                              <1> readi:
  2075                              <1> 	; 03/02/2022
  2076                              <1> 	; 20/05/2015
  2077                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2078                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2079                              <1> 	;
  2080                              <1> 	; Reads from an inode whose number in R1
  2081                              <1> 	; 
  2082                              <1> 	; INPUTS ->
  2083                              <1> 	;    r1 - inode number
  2084                              <1> 	;    u.count - byte count user desires
  2085                              <1> 	;    u.base - points to user buffer
  2086                              <1> 	;    u.fofp - points to word with current file offset
  2087                              <1> 	; OUTPUTS ->
  2088                              <1> 	;    u.count - cleared
  2089                              <1> 	;    u.nread - accumulates total bytes passed back
  2090                              <1> 	;
  2091                              <1> 	; ((AX = R1)) input/output
  2092                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2093                              <1>         ;    ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -14/07/2022- 
  2094                              <1> 
  2095 000049CA 31D2                <1> 	xor	edx, edx ; 0
  2096 000049CC 8915[28650000]      <1> 	mov 	[u.nread], edx ; 0
  2097                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2098 000049D2 668915[5F650000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2099 000049D9 3915[24650000]      <1> 	cmp 	[u.count], edx ; 0
  2100                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2101 000049DF 7701                <1> 	ja 	short readi_1 ; 1f
  2102                              <1> 		 ; bgt 1f / yes, branch
  2103 000049E1 C3                  <1> 	retn
  2104                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2105                              <1> readi_1: ; 1:
  2106                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2107 000049E2 6683F828            <1> 	cmp	ax, 40
  2108                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2109                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2110                              <1>         ;ja	dskr 
  2111                              <1> 		 ; ble 1f / yes, branch
  2112                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2113                              <1> 		 ;         / read file with i-node number (r1)
  2114                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2115                              <1> 	; 03/02/2022
  2116 000049E6 7605                <1> 	jna	short readi_3
  2117 000049E8 E9CF000000          <1> 	jmp	dskr
  2118                              <1> readi_3:
  2119                              <1> 	; (20/05/2015)
  2120 000049ED 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2121                              <1> 	; 1:
  2122 000049EE 0FB6D8              <1> 	movzx	ebx, al
  2123                              <1> 	; 03/02/2022
  2124 000049F1 C1E302              <1> 	shl	ebx, 2
  2125                              <1> 	;shl	bx, 2
  2126                              <1> 		 ; asl r1 / multiply inode number by 2
  2127 000049F4 81C3[F8490000]      <1> 	add	ebx, readi_2 - 4
  2128 000049FA FF23                <1> 	jmp	dword [ebx]	
  2129                              <1> 		 ; jmp *1f-2(r1)
  2130                              <1> readi_2: ; 1:
  2131 000049FC [484A0000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2132                              <1> 		 ;rtty / tty; r1=2
  2133                              <1> 		 ;rppt / ppt; r1=4
  2134 00004A00 [984A0000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2135                              <1> 		 ;rmem / mem; r1=6
  2136                              <1> 		 ;rrf0 / rf0
  2137                              <1> 		 ;rrk0 / rk0
  2138                              <1> 		 ;rtap / tap0
  2139                              <1> 		 ;rtap / tap1
  2140                              <1> 		 ;rtap / tap2
  2141                              <1> 		 ;rtap / tap3
  2142                              <1> 		 ;rtap / tap4
  2143                              <1> 		 ;rtap / tap5
  2144                              <1> 		 ;rtap / tap6
  2145                              <1> 		 ;rtap / tap7
  2146 00004A04 [82520000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2147 00004A08 [82520000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2148 00004A0C [82520000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2149 00004A10 [82520000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2150 00004A14 [82520000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2151 00004A18 [82520000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2152 00004A1C [AD4A0000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2153 00004A20 [944A0000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2154                              <1> 		 ;rcvt / tty0
  2155 00004A24 [944A0000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2156                              <1> 		 ;rcvt / tty1
  2157 00004A28 [944A0000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2158                              <1> 		 ;rcvt / tty2
  2159 00004A2C [944A0000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2160                              <1> 		 ;rcvt / tty3
  2161 00004A30 [944A0000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2162                              <1> 		 ;rcvt / tty4
  2163 00004A34 [944A0000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2164                              <1> 		 ;rcvt / tty5
  2165 00004A38 [944A0000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2166                              <1> 		 ;rcvt / tty6
  2167 00004A3C [944A0000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2168                              <1> 		 ;rcvt / tty7
  2169 00004A40 [944A0000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2170                              <1> 		 ;rcrd / crd
  2171 00004A44 [944A0000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2172                              <1> 
  2173                              <1> rtty: ; / read from console tty
  2174                              <1> 	; 03/02/2022
  2175                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2176                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2177                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2178                              <1> 	;	     must be written immediate on video page (screen)
  2179                              <1> 	;	     when it is required.	
  2180                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2181                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2182                              <1> 	;
  2183                              <1> 	; Console tty buffer is PC keyboard buffer
  2184                              <1> 	; and keyboard-keystroke handling is different than original
  2185                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2186                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2187                              <1> 	;
  2188                              <1> 	; 06/12/2013
  2189 00004A48 0FB61D[49650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2190 00004A4F 8A83[53620000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2191                              <1> rttys:
  2192                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2193                              <1> 	               ; / of the control and status block
  2194                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2195                              <1> 		       ; / tty buffer
  2196                              <1> 	; 28/07/2013
  2197 00004A55 A2[4E650000]        <1> 	mov 	[u.ttyn], al
  2198                              <1> 	; 13/01/2014
  2199 00004A5A FEC0                <1> 	inc	al
  2200 00004A5C A2[30650000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2201                              <1> rtty_nc: ; 01/02/2014
  2202                              <1> 	; 29/09/2013
  2203                              <1> 	;mov	ecx, 10
  2204                              <1> 	; 03/02/2022
  2205 00004A61 29C9                <1> 	sub	ecx, ecx
  2206 00004A63 B10A                <1> 	mov	cl, 10
  2207                              <1> rtty_1: 	; 01/02/2014
  2208                              <1> 	;push 	cx ; 29/09/2013
  2209                              <1> 	; 03/02/2022
  2210 00004A65 51                  <1> 	push	ecx
  2211                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2212 00004A66 B001                <1> 	mov 	al, 1
  2213 00004A68 E8200B0000          <1> 	call 	getc
  2214                              <1> 	; 03/02/2022
  2215 00004A6D 59                  <1> 	pop	ecx
  2216                              <1> 	;pop 	cx ; 29/09/2013	
  2217 00004A6E 7516                <1> 	jnz	short rtty_2
  2218                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2219                              <1> 	               ; / of chars. Is this number non-zero?
  2220 00004A70 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2221                              <1> 	; 05/10/2013
  2222 00004A72 8A25[4E650000]      <1> 	mov	ah, [u.ttyn]
  2223                              <1> 	; 29/09/2013
  2224 00004A78 E898FBFFFF          <1> 	call	sleep
  2225                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2226                              <1>                 ;           / (120 chars.)
  2227                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2228 00004A7D EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2229                              <1> 
  2230                              <1> rtty_idle:
  2231                              <1> 	; 29/07/2013
  2232 00004A7F E804FBFFFF          <1> 	call 	idle
  2233 00004A84 EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2234                              <1> 	;1:
  2235                              <1> 		; tst 2(r5) / is the number of characters zero
  2236                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2237                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2238                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2239                              <1> 		          ; / contains the next char.
  2240                              <1> 		; dec 2(r5) / decrement the character count
  2241                              <1> rtty_2:
  2242 00004A86 30C0                <1> 	xor 	al, al
  2243 00004A88 E8000B0000          <1> 	call 	getc
  2244 00004A8D E896000000          <1> 	call	passc
  2245                              <1> 		; jsr r0,passc / move the character to core (user)
  2246                              <1> 	;; 17/10/2015 - 16/07/2015
  2247                              <1> 	; 19/06/2014
  2248                              <1> 	;;jnz	short rtty_nc
  2249 00004A92 58                  <1> 	pop	eax  ; (20/05/2015)
  2250 00004A93 C3                  <1> 	retn 
  2251                              <1> ;ret1:
  2252                              <1> 		; jmp ret / return to caller via 'ret'
  2253                              <1> 
  2254                              <1> rcvt:   ; < receive/read character from tty >
  2255                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2256                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2257                              <1> 	;
  2258                              <1> 	; Retro UNIX 8086 v1 modification !
  2259                              <1> 	; 
  2260                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2261                              <1> 	;		(exactly different than this one)
  2262                              <1> 	;	was in 'u9.s' file.
  2263                              <1> 	;
  2264 00004A94 2C0A                <1> 	sub 	al, 10
  2265                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2266                              <1> 	; 16/07/2013
  2267                              <1> 	; 21/05/2013
  2268 00004A96 EBBD                <1>         jmp     short rttys
  2269                              <1>       
  2270                              <1> ;rppt: / read paper tape
  2271                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2272                              <1> ;			 / places
  2273                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2274                              <1> ;		       / also enables read bit in prs
  2275                              <1> ;	jsr	r0,passc / place character in users buffer area
  2276                              <1> ;	br	rppt
  2277                              <1> 
  2278                              <1> rmem: ; / transfer characters from memory to a user area of core
  2279                              <1> 	; 17/10/2015
  2280                              <1> 	; 11/06/2015
  2281                              <1> 	; 24/05/2015
  2282                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2283                              <1> 	;
  2284 00004A98 8B35[10650000]      <1> 	mov     esi, [u.fofp]
  2285                              <1> rmem_1:
  2286 00004A9E 8B1E                <1>         mov     ebx, [esi]        
  2287                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2288                              <1> 		               ; / to be transferred to user
  2289 00004AA0 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2290                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2291                              <1> 			    ; / char in memory file
  2292 00004AA2 8A03                <1> 	mov	al, [ebx]
  2293                              <1> 		; movb (r1),r1 / get character from memory file, 
  2294                              <1> 		             ; / put it in r1
  2295 00004AA4 E87F000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2296                              <1> 			     ;  / the next byte of the users core area
  2297                              <1> 		; br rmem / continue
  2298 00004AA9 75F3                <1> 	jnz	short rmem_1
  2299                              <1> ret_:
  2300 00004AAB 58                  <1> 	pop	eax ; 09/06/2015
  2301 00004AAC C3                  <1> 	retn
  2302                              <1> 
  2303                              <1> rlpr:
  2304                              <1> ;1:
  2305                              <1> ;rcrd:
  2306 00004AAD C705[4F650000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2306 00004AB5 0000                <1>
  2307 00004AB7 E925E6FFFF          <1> 	jmp	error
  2308                              <1> 		;jmp	error / see 'error' routine
  2309                              <1> 
  2310                              <1> dskr:
  2311                              <1> 	; 19/07/2022
  2312                              <1> 	; 12/10/2015
  2313                              <1> 	; 21/08/2015
  2314                              <1> 	; 25/07/2015
  2315                              <1> 	; 10/07/2015
  2316                              <1> 	; 16/06/2015
  2317                              <1> 	; 31/05/2015
  2318                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2319                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2320                              <1> dskr_0:
  2321 00004ABC 50                  <1> 	push	eax
  2322                              <1> 		; mov (sp),r1 / i-number in r1
  2323                              <1> 	; AX = i-number
  2324 00004ABD E834FDFFFF          <1> 	call	iget
  2325                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2326 00004AC2 0FB715[F8610000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2327                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2328 00004AC9 8B1D[10650000]      <1> 	mov	ebx, [u.fofp]
  2329 00004ACF 2B13                <1> 	sub	edx, [ebx]
  2330                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2331                              <1>         ; 12/10/2015
  2332                              <1> 	; jna     short ret_ 
  2333                              <1> 		; blos ret
  2334 00004AD1 7709                <1> 	ja	short dskr_1
  2335                              <1> 	;
  2336                              <1> dskr_retn: ; 12/10/2015
  2337 00004AD3 58                  <1> 	pop	eax
  2338 00004AD4 C605[61650000]00    <1> 	mov	byte [u.kcall], 0
  2339 00004ADB C3                  <1> 	retn	
  2340                              <1> dskr_1: 
  2341 00004ADC 3B15[24650000]      <1> 	cmp     edx, [u.count] 
  2342                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2343                              <1> 			       ; / to carry out read
  2344 00004AE2 7306                <1> 	jnb	short dskr_2
  2345                              <1> 		; bhis 1f
  2346 00004AE4 8915[24650000]      <1> 	mov	[u.count], edx
  2347                              <1> 		; mov r2,u.count / no, just read to end of file
  2348                              <1> dskr_2: ; 1:
  2349                              <1> 	; AX = i-number
  2350 00004AEA E89EFBFFFF          <1> 	call	mget
  2351                              <1> 		; jsr r0,mget / returns physical block number of block 
  2352                              <1> 			    ; / in file where offset points
  2353                              <1> 	; EAX = physical block number
  2354 00004AEF E8CD080000          <1> 	call	dskrd
  2355                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2356                              <1> 			     ; / 1st word of data in buffer
  2357                              <1> 	; 09/06/2015
  2358 00004AF4 803D[61650000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2359 00004AFB 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2360 00004AFD 66833D[5F650000]00  <1> 	cmp	word [u.pcount], 0
  2361 00004B05 7705                <1> 	ja	short dskr_4
  2362                              <1> dskr_3:
  2363                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2364 00004B07 E857000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2365                              <1> dskr_4:
  2366                              <1> 	; EBX (r5) = system (I/O) buffer address -physical-
  2367 00004B0C E83D030000          <1> 	call	sioreg
  2368                              <1> 		; jsr r0,sioreg
  2369                              <1> 	
  2370                              <1> 	; 19/07/2022
  2371                              <1> 	;xchg	esi, edi
  2372                              <1> 	
  2373                              <1> 	; 19/07/2022
  2374                              <1> 	;  EDX = user data offset (previous value of [u.pbase])
  2375                              <1> 	;  ESI = pointer to file offset 
  2376                              <1> 	;  EDI = system (I/O) buffer offset
  2377                              <1> 	;  ECX = byte count
  2378                              <1> 	;  EBX = system buffer (data) address	
  2379                              <1> 	;  EAX = remain bytes after byte count within page frame 
  2380                              <1> 
  2381 00004B11 010E                <1> 	add	[esi], ecx 
  2382                              <1> 			; new file offset (old offset + byte count)
  2383                              <1> 	;
  2384 00004B13 89FE                <1> 	mov	esi, edi ; sector (I/O) buffer offset
  2385 00004B15 89D7                <1> 	mov	edi, edx
  2386                              <1> 
  2387                              <1> 	; EDI = file (user data) offset
  2388                              <1> 	; ESI = sector (I/O) buffer offset
  2389                              <1> 	; ECX = byte count
  2390 00004B17 F3A4                <1> 	rep	movsb
  2391                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2392                              <1> 		                 ; / starting at u.base
  2393                              <1> 		; dec r3
  2394                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2395                              <1> 	; 25/07/2015
  2396                              <1> 	; eax = remain bytes in buffer
  2397                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2398 00004B19 09C0                <1> 	or	eax, eax
  2399 00004B1B 75EA                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2400                              <1> 	; 03/08/2013
  2401                              <1> 	;pop	eax
  2402 00004B1D 390D[24650000]      <1> 	cmp	[u.count], ecx ; 0
  2403                              <1> 		; tst u.count / all bytes read off disk
  2404                              <1> 		; bne dskr
  2405                              <1> 		; br ret
  2406                              <1>         ;ja      short dskr_0
  2407                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2408                              <1> 	;retn
  2409                              <1> 	; 12/10/2015
  2410 00004B23 76AE                <1> 	jna	short dskr_retn
  2411 00004B25 58                  <1> 	pop	eax  ; (i-node number)
  2412 00004B26 EB94                <1> 	jmp	short dskr_0
  2413                              <1> 	
  2414                              <1> passc:
  2415                              <1> 	; 18/10/2015
  2416                              <1> 	; 10/07/2015
  2417                              <1> 	; 01/07/2015
  2418                              <1> 	; 08/06/2015
  2419                              <1> 	; 04/06/2015
  2420                              <1> 	; 20/05/2015
  2421                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2422                              <1> 	;
  2423                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2424                              <1> 	;		      to physical address
  2425 00004B28 66833D[5F650000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2426                              <1> 			     ; 1-4095 --> use previous physical base address
  2427                              <1> 			     ; in [u.pbase]
  2428 00004B30 7705                <1> 	ja	short passc_3
  2429                              <1> 	; 08/06/2015 - 10/07/2015
  2430 00004B32 E82C000000          <1> 	call	trans_addr_w
  2431                              <1> passc_3:
  2432                              <1> 	; 19/05/2015
  2433 00004B37 66FF0D[5F650000]    <1> 	dec	word [u.pcount]
  2434                              <1> 	;
  2435 00004B3E 8B1D[5B650000]      <1> 	mov	ebx, [u.pbase]
  2436 00004B44 8803                <1> 	mov	[ebx], al
  2437                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2438                              <1> 		               ; / users buffer
  2439 00004B46 FF05[20650000]      <1> 	inc	dword [u.base]
  2440                              <1> 		; inc u.base / increment the pointer to point to 
  2441                              <1> 			  ; / the next byte in users buffer
  2442 00004B4C FF05[5B650000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2443 00004B52 FF05[28650000]      <1> 	inc	dword [u.nread]
  2444                              <1> 		; inc u.nread / increment the number of bytes read
  2445 00004B58 FF0D[24650000]      <1> 	dec	dword [u.count]
  2446                              <1> 		; dec u.count / decrement the number of bytes to be read
  2447                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2448 00004B5E C3                  <1> 	retn
  2449                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2450                              <1> 		             ; / 'readi' by:
  2451                              <1> 		;/ (1) pop the return address off the stack into r0
  2452                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2453                              <1> 	;1:
  2454                              <1> 		; clr	*$ps / clear processor status
  2455                              <1> 		; rts r0 / return to address currently on top of stack
  2456                              <1> 
  2457                              <1> trans_addr_r:
  2458                              <1> 	; Translate virtual address to physical address 
  2459                              <1> 	; for reading from user's memory space
  2460                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2461                              <1> 	; 18/10/2015
  2462                              <1> 	; 10/07/2015
  2463                              <1> 	; 09/06/2015
  2464                              <1> 	; 08/06/2015 
  2465                              <1> 	; 04/06/2015
  2466                              <1> 	;
  2467                              <1> 	; 18/10/2015
  2468 00004B5F 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2469 00004B61 EB04                <1> 	jmp 	short trans_addr_rw
  2470                              <1> 
  2471                              <1> 	;push	eax
  2472                              <1> 	;push	ebx
  2473                              <1> 	;mov	ebx, [u.base]
  2474                              <1> 	;call	get_physical_addr ; get physical address
  2475                              <1> 	;;jnc	short cpass_0
  2476                              <1> 	;jnc	short passc_1
  2477                              <1> 	;mov	[u.error], eax
  2478                              <1> 	;;pop	ebx
  2479                              <1> 	;;pop	eax
  2480                              <1> 	;jmp	error
  2481                              <1> ;cpass_0:
  2482                              <1> 	; 18/10/2015
  2483                              <1> 	; 20/05/2015
  2484                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2485                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2486                              <1> 	;pop	ebx
  2487                              <1> 	;pop	eax
  2488                              <1> 	;retn	; 08/06/2015
  2489                              <1> 
  2490                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2491                              <1> trans_addr_w:
  2492                              <1> 	; Translate virtual address to physical address 
  2493                              <1> 	; for writing to user's memory space
  2494                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2495                              <1> 	; 18/10/2015
  2496                              <1> 	; 29/07/2015
  2497                              <1> 	; 10/07/2015
  2498                              <1> 	; 09/06/2015
  2499                              <1> 	; 08/06/2015
  2500                              <1> 	; 04/06/2015 (passc)
  2501                              <1> 	;
  2502                              <1> 	; 18/10/2015
  2503 00004B63 29D2                <1> 	sub	edx, edx
  2504 00004B65 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2505                              <1> trans_addr_rw:
  2506 00004B67 50                  <1> 	push	eax
  2507 00004B68 53                  <1> 	push	ebx
  2508                              <1> 	; 18/10/2015
  2509 00004B69 52                  <1> 	push 	edx ; r/w sign (in DL)
  2510                              <1> 	;
  2511 00004B6A 8B1D[20650000]      <1> 	mov	ebx, [u.base]
  2512 00004B70 E854DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2513 00004B75 730A                <1> 	jnc	short passc_0
  2514 00004B77 A3[4F650000]        <1> 	mov	[u.error], eax
  2515                              <1> 	;pop	edx
  2516                              <1> 	;pop 	ebx
  2517                              <1> 	;pop	eax
  2518 00004B7C E960E5FFFF          <1> 	jmp	error
  2519                              <1> passc_0:
  2520 00004B81 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2521 00004B84 5A                  <1> 	pop	edx ; 18/10/2015
  2522 00004B85 7517                <1> 	jnz	short passc_1
  2523                              <1> 	; 18/10/2015
  2524 00004B87 20D2                <1> 	and 	dl, dl
  2525 00004B89 7413                <1> 	jz	short passc_1
  2526                              <1> 	; 20/05/2015
  2527                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2528                              <1> 	; EBX = linear address
  2529 00004B8B 51                  <1> 	push 	ecx
  2530 00004B8C 53                  <1> 	push	ebx ; * ; 03/02/2022 (BugFix)
  2531 00004B8D E8A8DBFFFF          <1> 	call 	copy_page
  2532 00004B92 5B                  <1> 	pop	ebx ; * ; 03/02/2022 (BugFix)
  2533 00004B93 59                  <1> 	pop	ecx
  2534 00004B94 7217                <1> 	jc	short passc_2
  2535                              <1> 	; 03/02/2022
  2536                              <1> 	;push	eax ; physical address of the new/allocated page
  2537                              <1> 	;call	add_to_swap_queue
  2538                              <1> 	;pop	eax
  2539                              <1> 	; 18/10/2015
  2540 00004B96 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2541                              <1> 	;mov 	ecx, PAGE_SIZE
  2542                              <1> 	;sub	ecx, ebx 
  2543 00004B9C 01D8                <1> 	add	eax, ebx  
  2544                              <1> passc_1: 
  2545                              <1> 	; 18/10/2015
  2546                              <1> 	; 20/05/2015
  2547 00004B9E A3[5B650000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2548 00004BA3 66890D[5F650000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2549 00004BAA 5B                  <1> 	pop	ebx
  2550 00004BAB 58                  <1> 	pop	eax
  2551 00004BAC C3                  <1> 	retn	; 08/06/2015
  2552                              <1> passc_2:
  2553 00004BAD C705[4F650000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2553 00004BB5 0000                <1>
  2554                              <1> 	;pop 	ebx
  2555                              <1> 	;pop	eax
  2556 00004BB7 E925E5FFFF          <1> 	jmp	error
  2557                              <1> 
  2558                              <1> writei:
  2559                              <1> 	; 13/06/2022
  2560                              <1> 	; 03/02/2022
  2561                              <1> 	; 20/05/2015
  2562                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2563                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2564                              <1> 	;
  2565                              <1> 	; Write data to file with inode number in R1
  2566                              <1> 	; 
  2567                              <1> 	; INPUTS ->
  2568                              <1> 	;    r1 - inode number
  2569                              <1> 	;    u.count - byte count to be written
  2570                              <1> 	;    u.base - points to user buffer
  2571                              <1> 	;    u.fofp - points to word with current file offset
  2572                              <1> 	; OUTPUTS ->
  2573                              <1> 	;    u.count - cleared
  2574                              <1> 	;    u.nread - accumulates total bytes passed back	
  2575                              <1> 	; ((AX = R1))
  2576                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2577                              <1> 	;    ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -14/07/2022-	
  2578                              <1> 
  2579 00004BBC 31C9                <1> 	xor	ecx, ecx
  2580 00004BBE 890D[28650000]      <1> 	mov 	[u.nread], ecx  ; 0
  2581                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2582                              <1> 		            ; / read or write calls
  2583 00004BC4 66890D[5F650000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2584 00004BCB 390D[24650000]      <1> 	cmp 	[u.count], ecx
  2585                              <1> 	;	; tst u.count / test the byte count specified by the user
  2586 00004BD1 770B                <1> 	ja 	short writei_1 ; 1f
  2587                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2588                              <1> 
  2589                              <1> 	; 13/06/2022 - ('get/read LPT printer status' modification)
  2590 00004BD3 83F810              <1> 	cmp	eax, 16  ; LPR_INODE ; lpt (parallel port printer) ?
  2591 00004BD6 7505                <1> 	jne	short writei_0
  2592 00004BD8 E924010000          <1> 	jmp	lpr_stat	; get/read line status
  2593                              <1> writei_0:
  2594 00004BDD C3                  <1> 	retn
  2595                              <1> 	;	; rts r0 / no, return - no writing to do
  2596                              <1> writei_1: ;1:
  2597                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2598 00004BDE 6683F828            <1> 	cmp 	ax, 40
  2599                              <1> 		; cmp r1,$40.
  2600                              <1> 		; / does the i-node number indicate a special file?
  2601                              <1> 	;ja	dskw 
  2602                              <1> 		; bgt dskw / no, branch to standard file output
  2603                              <1> 	; 03/02/2022
  2604 00004BE2 7605                <1> 	jna	short writei_3
  2605 00004BE4 E958010000          <1> 	jmp	dskw
  2606                              <1> writei_3:
  2607                              <1> 	; (20/05/2015)
  2608 00004BE9 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2609 00004BEA 0FB6D8              <1> 	movzx	ebx, al
  2610                              <1> 	; 03/02/2022
  2611 00004BED C1E302              <1> 	shl	ebx, 2
  2612                              <1> 	;shl	bx, 2
  2613                              <1> 		; asl r1 / yes, calculate the index into the special file
  2614 00004BF0 81C3[F44B0000]      <1> 	add	ebx, writei_2 - 4
  2615 00004BF6 FF23                <1> 	jmp	dword [ebx]	
  2616                              <1> 		; jmp *1f-2(r1)
  2617                              <1> 		; / jump table and jump to the appropriate routine
  2618                              <1> writei_2: ;1:
  2619 00004BF8 [444C0000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2620                              <1> 		 ;wtty / tty; r1=2
  2621                              <1> 		 ;wppt / ppt; r1=4
  2622 00004BFC [974C0000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2623                              <1> 		 ;wmem / mem; r1=6
  2624                              <1> 		 ;wrf0 / rf0
  2625                              <1> 		 ;wrk0 / rk0
  2626                              <1> 		 ;wtap / tap0
  2627                              <1> 		 ;wtap / tap1
  2628                              <1> 		 ;wtap / tap2
  2629                              <1> 		 ;wtap / tap3
  2630                              <1> 		 ;wtap / tap4
  2631                              <1> 		 ;wtap / tap5
  2632                              <1> 		 ;wtap / tap6
  2633                              <1> 		 ;wtap / tap7
  2634 00004C00 [F7520000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2635 00004C04 [F7520000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2636 00004C08 [F7520000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2637 00004C0C [F7520000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2638 00004C10 [F7520000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2639 00004C14 [F7520000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2640 00004C18 [C74C0000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2641 00004C1C [914C0000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2642                              <1> 		 ;xmtt / tty0
  2643 00004C20 [914C0000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2644                              <1> 		 ;xmtt / tty1
  2645 00004C24 [914C0000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2646                              <1> 		 ;xmtt / tty2
  2647 00004C28 [914C0000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2648                              <1> 		 ;xmtt / tty3
  2649 00004C2C [914C0000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2650                              <1> 		 ;xmtt / tty4
  2651 00004C30 [914C0000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2652                              <1> 		 ;xmtt / tty5
  2653 00004C34 [914C0000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2654                              <1> 		 ;xmtt / tty6
  2655 00004C38 [914C0000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2656                              <1> 		 ;xmtt / tty7
  2657 00004C3C [914C0000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2658                              <1> 		; / wlpr / lpr
  2659 00004C40 [914C0000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2660                              <1> 
  2661                              <1> wtty: ; write to console tty (write to screen)
  2662                              <1> 	; 03/02/2022
  2663                              <1> 	; 18/11/2015
  2664                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2665                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2666                              <1> 	;
  2667                              <1> 	; Console tty output is on current video page
  2668                              <1> 	; Console tty character output procedure is changed here
  2669                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2670                              <1> 	;
  2671 00004C44 0FB61D[49650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2672 00004C4B 8AA3[53620000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2673 00004C51 88E0                <1> 	mov	al, ah ; 07/07/2014
  2674                              <1> wttys:	
  2675                              <1> 	; 10/10/2013
  2676 00004C53 8825[4E650000]      <1> 	mov 	[u.ttyn], ah
  2677                              <1> 	; 13/01/2014
  2678 00004C59 FEC0                <1> 	inc	al
  2679 00004C5B A2[31650000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2680                              <1> wtty_nc: ; 15/05/2013
  2681                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2682 00004C60 E889010000          <1> 	call	cpass
  2683                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2684                              <1> 		             ; / none go to return address in syswrite
  2685                              <1> 		; tst r1 / is character = null
  2686                              <1> 		; beq wtty / yes, get next character
  2687                              <1> 	; 10/10/2013
  2688 00004C65 7428                <1> 	jz	short wret
  2689                              <1> 	;1 :
  2690                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2691                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2692                              <1> 		;	          / than 20
  2693                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2694                              <1> 	; 27/06/2014
  2695                              <1> wtty_1:
  2696                              <1> 	; AH = tty number
  2697                              <1> 	; AL = ASCII code of the character
  2698                              <1> 	; 15/04/2014
  2699                              <1> 	;push	ax
  2700                              <1> 	; 03/02/2022
  2701 00004C67 50                  <1> 	push	eax
  2702 00004C68 E88E090000          <1> 	call	putc ; 14/05/2013
  2703 00004C6D 731D                <1> 	jnc	short wtty_2
  2704                              <1> 	; 18/11/2015
  2705 00004C6F E814F9FFFF          <1> 	call	idle
  2706                              <1> 	;mov	ax, [esp]
  2707                              <1> 	; 03/02/2022
  2708 00004C74 8B0424              <1> 	mov	eax, [esp]
  2709 00004C77 E87F090000          <1> 	call	putc
  2710 00004C7C 730E                <1> 	jnc	short wtty_2 
  2711                              <1> 	; 02/06/2014
  2712 00004C7E 8A25[4E650000]      <1> 	mov	ah, [u.ttyn]
  2713 00004C84 E88CF9FFFF          <1> 	call	sleep
  2714                              <1> 	; 03/02/2022
  2715 00004C89 58                  <1> 	pop	eax
  2716                              <1> 	;pop	ax
  2717 00004C8A EBDB                <1> 	jmp 	short wtty_1
  2718                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2719                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2720                              <1> 			      ; / console tty and
  2721                              <1> 		; br 	2f / place character in list; if none available
  2722                              <1> 		   	  ; / branch to put process to sleep
  2723                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2724                              <1> wtty_2:
  2725                              <1> 	; 15/04/2014
  2726                              <1> 	;pop	ax
  2727                              <1> 	; 03/02/2022
  2728 00004C8C 58                  <1> 	pop	eax
  2729 00004C8D EBD1                <1> 	jmp	short wtty_nc
  2730                              <1> 		; br wtty
  2731                              <1> wret:	; 10/10/2013 (20/05/2015)
  2732 00004C8F 58                  <1> 	pop	eax
  2733 00004C90 C3                  <1> 	retn
  2734                              <1> 	;2:
  2735                              <1> 		;mov	r1,-(sp) / place character on stack
  2736                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2737                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2738                              <1> 		;br	1b / try again to place character in clist and output
  2739                              <1> 
  2740                              <1> xmtt:   ; < send/write character to tty >
  2741                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2742                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2743                              <1> 	;
  2744                              <1> 	; Retro UNIX 8086 v1 modification !
  2745                              <1> 	; 
  2746                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2747                              <1> 	;		(exactly different than this one)
  2748                              <1> 	;	was in 'u9.s' file.
  2749                              <1> 	;
  2750 00004C91 2C0A                <1> 	sub 	al, 10
  2751                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2752                              <1> 	; 10/10/2013
  2753 00004C93 88C4                <1> 	mov	ah, al
  2754                              <1> 	; 28/07/2013
  2755 00004C95 EBBC                <1> 	jmp	short wttys
  2756                              <1> 
  2757                              <1> ;wppt:
  2758                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2759                              <1> ;		         / if none return to writei's calling routine
  2760                              <1> ;	jsr	r0,pptoc / output character on ppt
  2761                              <1> ;	br	wppt
  2762                              <1> 
  2763                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2764                              <1> 	; 17/10/2015
  2765                              <1> 	; 11/06/2015
  2766                              <1> 	; 24/05/2015
  2767                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2768                              <1> 	;
  2769 00004C97 813D[09070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2769 00004C9D [AB450000]          <1>
  2770 00004CA1 7415                <1>         je      short wmem_acc_err
  2771                              <1> 	;
  2772 00004CA3 8B35[10650000]      <1>         mov     esi, [u.fofp] 
  2773                              <1> wmem_1:
  2774 00004CA9 E840010000          <1> 	call	cpass
  2775                              <1> 		; jsr r0,cpass / get next character from users area of
  2776                              <1> 			     ; / core and put it in r1
  2777                              <1>         	; mov r1,-(sp) / put character on the stack
  2778                              <1> 	; 20/09/2013
  2779 00004CAE 74DF                <1> 	jz	short wret ; wmem_2  
  2780 00004CB0 8B1E                <1>         mov     ebx, [esi]
  2781                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2782 00004CB2 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2783                              <1> 		; inc *u.fofp / increment file offset to point to next
  2784                              <1> 			    ; / available location in file
  2785 00004CB4 8803                <1> 	mov	[ebx], al	
  2786                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2787                              <1> 			        ; / assigned to it
  2788 00004CB6 EBF1                <1> 	jmp	short wmem_1
  2789                              <1> 		; br wmem / continue
  2790                              <1> 	;1:
  2791                              <1> 	;jmp	error / ?
  2792                              <1> ;wmem_2:	
  2793                              <1> ;	; 20/09/2013
  2794                              <1> ;	pop	ax
  2795                              <1> ;	retn
  2796                              <1> 
  2797                              <1> wmem_acc_err:
  2798 00004CB8 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2798 00004CC0 0000                <1>
  2799 00004CC2 E91AE4FFFF          <1> 	jmp	error
  2800                              <1> 
  2801                              <1> ;wlpr:
  2802                              <1> 	; 13/06/2022
  2803                              <1>         ;mov	dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2804                              <1> 	;jmp	error   ; ... Printing procedure will be located here ...
  2805                              <1> 		;/	jsr	r0,cpass
  2806                              <1> 		;/	cmp	r0,$'a
  2807                              <1> 		;/	blo	1f
  2808                              <1> 		;/	cmp	r1,$'z
  2809                              <1> 		;/	bhi	1f
  2810                              <1> 		;/	sub	$40,r1
  2811                              <1> 		;/1:
  2812                              <1> 		;/	jsr	r0,lptoc
  2813                              <1> 		;/	br	wlpr
  2814                              <1> 		; br rmem / continue
  2815                              <1> 
  2816                              <1> ; 13/06/2022 - Retro UNIX 386 v1 - PRINTER BIOS (Functions)
  2817                              <1> 
  2818                              <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM)
  2819                              <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987
  2820                              <1> ;; 23/03/2018 - Retro DOS v2.0
  2821                              <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2)
  2822                              <1> 
  2823                              <1> ; IBM ROMBIOS (INT 17h) STATUS BITS
  2824                              <1> 
  2825                              <1> NOTBUSYSTATUS	equ 10000000b	; NOT BUSY
  2826                              <1> ACKSTATUS	equ 01000000b	; ACKNOWLEDGE (FOR WHAT?)
  2827                              <1> NOPAPERSTATUS	equ 00100000b	; NO MORE PAPER
  2828                              <1> SELECTEDSTATUS	equ 00010000b	; THE PRINTER SAID IT WAS SELECTED
  2829                              <1> IOERRSTATUS	equ 00001000b	; SOME KIND ERROR
  2830                              <1> RESERVED	equ 00000110b	; NOPS
  2831                              <1> TIMEOUTSTATUS	equ 00000001b	; TIME OUT.
  2832                              <1> 
  2833                              <1> ;----------------------------------------------------------------
  2834                              <1> ;								:
  2835                              <1> ;		WRITE TO PRINTER DEVICE 			:
  2836                              <1> ;								:
  2837                              <1> ;   CX has count of bytes to be printed 			:
  2838                              <1> ;   ES:DI point to source buffer contains characters		:
  2839                              <1> ;   AuxNum (in msbio.asm) has printer number			:
  2840                              <1> ;								:
  2841                              <1> ;----------------------------------------------------------------
  2842                              <1> 
  2843                              <1> wlpr:
  2844                              <1> 	; 14/07/2022
  2845                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2846                              <1> PRN$WRIT:
  2847                              <1> 	; INPUT:
  2848                              <1> 	;	[u.count] = count of characters to be printed
  2849                              <1> 	;	[u.base] = buffer address in user's memory space
  2850                              <1> 	;
  2851                              <1> 	;	(if ECX = 0, printer status will be returned)
  2852                              <1> 	
  2853                              <1> 	;xor	ebx, ebx
  2854                              <1> PRN$LOOP:
  2855 00004CC7 E822010000          <1> 	call	cpass		  ; Get a character into AL
  2856 00004CCC 7431                <1> 	jz	short pr_exit
  2857                              <1> 	;
  2858 00004CCE B302                <1> 	mov	bl, 2  ; retry count
  2859                              <1> PRN$OUT:
  2860                              <1> 	; al = character which will be printed
  2861 00004CD0 30E4                <1> 	xor	ah, ah ; 0	  ; PRINT THE CHARACTER IN (AL)
  2862 00004CD2 E850000000          <1> 	call	PRNOP
  2863 00004CD7 74EE                <1> 	jz	short PRN$LOOP 	  ; if error, try to print again
  2864                              <1> PrRetry:
  2865                              <1> 	; al = character
  2866 00004CD9 FECB                <1> 	dec	bl
  2867 00004CDB 75F3                <1> 	jnz	short PRN$OUT
  2868                              <1> pr_err_exit:
  2869 00004CDD 0FB6C0              <1> 	movzx	eax, al
  2870 00004CE0 A3[4F650000]        <1> 	mov	[u.error], eax
  2871 00004CE5 A3[00650000]        <1> 	mov	[u.r0], eax ; error code in AL
  2872                              <1> 	;mov 	ebp, [u.sp]
  2873 00004CEA 8B1D[F8640000]      <1> 	mov	ebx, [u.sp] ; 14/07/2022
  2874                              <1> 			; Kernel stack at the beginning of sys call
  2875 00004CF0 8B15[28650000]      <1> 	mov	edx, [u.nread]
  2876 00004CF6 4A                  <1> 	dec	edx ; last char failed
  2877                              <1> 	;mov	[ebp+20], edx ; count of printed characters in edx
  2878 00004CF7 895314              <1> 	mov	[ebx+20], edx ; 14/07/2022
  2879 00004CFA E9E2E3FFFF          <1> 	jmp	error
  2880                              <1> pr_exit:
  2881 00004CFF 58                  <1> 	pop	eax ; inode number
  2882                              <1> 
  2883                              <1> 	;mov	eax, [u.nread]
  2884                              <1> 	;mov	[u.r0], eax ; count of printed chacters
  2885                              <1> 	;jmp	sysret
  2886 00004D00 C3                  <1> 	retn	; return from writei to syswrite (rw0)
  2887                              <1> 
  2888                              <1> ; 13/06/2022
  2889                              <1> 
  2890                              <1> ;----------------------------------------------------------------
  2891                              <1> ;								:
  2892                              <1> ;		PRINTER STATUS ROUTINE				:
  2893                              <1> ;								:
  2894                              <1> ;----------------------------------------------------------------
  2895                              <1> ;
  2896                              <1> 
  2897                              <1> lpr_stat:
  2898                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2899                              <1> PRN$STAT:
  2900 00004D01 E81F000000          <1> 	call	PRNSTAT		  ; get the status
  2901 00004D06 750E                <1> 	jnz	short prn_stat_retn
  2902                              <1> 				  ; if error jump to error routine
  2903                              <1> 	;mov	al, 9		  ; AGAIN, ASSUME OUT OF PAPER...
  2904 00004D08 B01F                <1> 	mov	al, ERR_PRN_PAPER
  2905 00004D0A F6C420              <1> 	test	ah, NOPAPERSTATUS
  2906 00004D0D 7507                <1> 	jnz	short prn_stat_retn
  2907 00004D0F F6C480              <1> 	test	ah, NOTBUSYSTATUS
  2908 00004D12 750D                <1> 	jnz	short prn_stat_ok ; if not busy return (with cf=0)
  2909 00004D14 B022                <1> 	mov	al, ERR_PRN_BUSY  ; else busy, return to busy exit
  2910                              <1> prn_stat_retn:
  2911                              <1> 	; al = error code
  2912                              <1> 	; ah = status flags
  2913 00004D16 A3[00650000]        <1> 	mov	[u.r0], eax
  2914                              <1> 	;movzx	eax, al
  2915                              <1> 	;mov 	[u.error], eax
  2916 00004D1B 58                  <1> 	pop	eax ; discard return address to syswrite
  2917 00004D1C E9E0E3FFFF          <1> 	jmp	sysret
  2918                              <1> prn_stat_ok:
  2919 00004D21 30C0                <1> 	xor	al, al ; 0
  2920 00004D23 EBF1                <1> 	jmp	short prn_stat_retn
  2921                              <1> 
  2922                              <1> ;
  2923                              <1> ;   PRNSTAT	get printer status
  2924                              <1> ;   PRNOP	print a character
  2925                              <1> ;
  2926                              <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS
  2927                              <1> ; printer routines.  The routines share code which calls on the bios and
  2928                              <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ
  2929                              <1> ; only by the value put into AH before the ROM-BIOS call.
  2930                              <1> ;
  2931                              <1> ;   INPUT	if PRNOP then character in AL
  2932                              <1> ;
  2933                              <1> ;   OUTPUT	- AL holds error code
  2934                              <1> ;		- AH status byte from printer
  2935                              <1> ;		- flag NZ if error
  2936                              <1> 
  2937                              <1> PRNSTAT:
  2938 00004D25 B402                <1> 	mov	ah, 2		  ; set command for get status 
  2939                              <1> 
  2940                              <1> PRNOP:
  2941                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2942                              <1> 	;
  2943                              <1> 	; Print character (on paper)
  2944                              <1> 
  2945                              <1> 	; INPUT:
  2946                              <1> 	;	al = character to be printed
  2947                              <1> 	; OUTPUT:
  2948                              <1> 	;	zf = 1 -> ok
  2949                              <1> 	;	zf = 0 -> error code in AL
  2950                              <1> 
  2951 00004D27 E8080B0000          <1> 	call	int17h	 ; call lpt bios
  2952                              <1> 	
  2953 00004D2C F6C408              <1> 	test	ah, IOERRSTATUS	  ; I/O ERROR?
  2954 00004D2F 740A                <1> 	jz	short short prnop_chk_nrdy ; NO, TRY NOT READY
  2955                              <1> 
  2956                              <1> 	; AT THIS POINT, WE KNOW WE HAVE AN ERROR.
  2957                              <1> 	; THE CONVERSE IS NOT TRUE.
  2958                              <1> 
  2959                              <1> 	;mov	al, 9		  ; FIRST, ASSUME OUT OF PAPER
  2960 00004D31 B01F                <1> 	mov	al, ERR_PRN_PAPER
  2961 00004D33 F6C420              <1> 	test	ah, NOPAPERSTATUS ; OUT OF PAPER SET?
  2962 00004D36 7502                <1> 	jnz	short PRNOP1	  ; YES, ERROR IS SET
  2963                              <1> 	;mov	al, ERR_PRN_IO
  2964 00004D38 FEC0                <1> 	inc	al		  ; INDICATE I/O ERROR
  2965                              <1> PRNOP1: 
  2966                              <1> 
  2967                              <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)
  2968                              <1> 
  2969 00004D3A C3                  <1> 	retn			  ; RETURN WITH ERROR
  2970                              <1>  
  2971                              <1> ; THE BITS SAID NO ERROR.
  2972                              <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE.
  2973                              <1> 
  2974                              <1> prnop_chk_nrdy:
  2975                              <1> 	;mov	al, 2		  ; ASSUME NOT-READY
  2976 00004D3B B019                <1> 	mov	al, ERR_PRN_TIMEOUT ; ''time out !' error
  2977                              <1> 	
  2978 00004D3D F6C401              <1> 	test	ah, TIMEOUTSTATUS ; IS TIME-OUT SET?
  2979                              <1> 				  ; IF NZ THEN ERROR, ELSE OK???
  2980                              <1> PRNOP2: 
  2981 00004D40 C3                  <1> 	retn
  2982                              <1> 
  2983                              <1> 
  2984                              <1> dskw: ; / write routine for non-special files
  2985                              <1> 	;
  2986                              <1> 	; 19/07/2022
  2987                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  2988                              <1> 	; 03/02/2022
  2989                              <1> 	; 25/07/2015
  2990                              <1> 	; 16/06/2015
  2991                              <1> 	; 09/06/2015
  2992                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2993                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2994                              <1> 	;
  2995                              <1> 	; 01/08/2013 (mkdir_w check)
  2996                              <1> 
  2997                              <1> 	;push	ax ; 26/04/2013
  2998                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2999                              <1> 	; 03/02/2022
  3000 00004D41 50                  <1> 	push	eax
  3001                              <1> 	; AX = inode number
  3002 00004D42 E8AFFAFFFF          <1> 	call	iget
  3003                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  3004                              <1> 		            ; / read i-node 'r1' into i-node area of core
  3005 00004D47 8B1D[10650000]      <1>         mov     ebx, [u.fofp] 
  3006 00004D4D 8B13                <1> 	mov 	edx, [ebx]
  3007                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  3008                              <1> 			       ; / in the fsp entry for this file] in r2
  3009 00004D4F 0315[24650000]      <1> 	add 	edx, [u.count]	
  3010                              <1> 		; add u.count,r2 / no. of bytes to be written
  3011                              <1> 			       ; / + file offset is put in r2
  3012                              <1> 	; 16/06/2015        
  3013 00004D55 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  3014 00004D5B 760F                <1> 	jna	short dskw_0
  3015 00004D5D C705[4F650000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  3015 00004D65 0000                <1>
  3016 00004D67 E975E3FFFF          <1> 	jmp	error
  3017                              <1> dskw_0:	
  3018 00004D6C 663B15[F8610000]    <1> 	cmp     dx, [i.size]
  3019                              <1> 		; cmp r2,i.size / is this greater than the present size of
  3020                              <1> 		              ; / the file?
  3021 00004D73 760C                <1> 	jna	short dskw_1
  3022                              <1> 		; blos 1f / no, branch
  3023 00004D75 668915[F8610000]    <1>         mov     [i.size], dx
  3024                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  3025                              <1> 			      ; / file offset + no. of data bytes
  3026 00004D7C E87FFBFFFF          <1> 	call	setimod
  3027                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  3028                              <1> 		          ; / modified), stuff time of modification into
  3029                              <1> 	          	  ; / core image of i-node
  3030                              <1> dskw_1: ; 1:	
  3031 00004D81 E807F9FFFF          <1> 	call	mget
  3032                              <1> 	; EAX = Block number
  3033                              <1> 		; jsr r0,mget / get the block no. in which to write 
  3034                              <1> 			    ; /	the next data byte
  3035                              <1> 	; eax = block number
  3036 00004D86 8B1D[10650000]      <1> 	mov     ebx, [u.fofp]
  3037 00004D8C 8B13                <1> 	mov	edx, [ebx]
  3038 00004D8E 81E2FF010000        <1> 	and	edx, 1FFh  
  3039                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  3040 00004D94 750C                <1> 	jnz	short dskw_2
  3041                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  3042                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  3043 00004D96 813D[24650000]0002- <1> 	cmp	dword [u.count], 512
  3043 00004D9E 0000                <1>
  3044                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  3045                              <1> 				  ; / an entire block? (i.e., no. of
  3046 00004DA0 7305                <1> 	jnb	short dskw_3
  3047                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  3048                              <1> 			; / Yes, branch. Don't have to read block
  3049                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  3050                              <1>    		; / overwritten).
  3051 00004DA2 E81A060000          <1> 	call	dskrd
  3052                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  3053                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  3054                              <1> dskw_3: ; 3:
  3055                              <1> 	; EAX (r1) = block/sector number
  3056 00004DA7 E879060000          <1> 	call	wslot
  3057                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  3058                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  3059 00004DAC 803D[61650000]00    <1> 	cmp	byte [u.kcall], 0
  3060 00004DB3 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  3061                              <1> 	;
  3062 00004DB5 66833D[5F650000]00  <1> 	cmp	word [u.pcount], 0
  3063 00004DBD 7705                <1> 	ja	short dskw_5
  3064                              <1> dskw_4:
  3065                              <1> 	; [u.base] = virtual address to transfer (as source address)
  3066 00004DBF E89BFDFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  3067                              <1> dskw_5:
  3068                              <1> 	; EBX (r5) = system (I/O) buffer address
  3069 00004DC4 E885000000          <1> 	call	sioreg
  3070                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3071                              <1> 			     ; / r1 = address of data, r2 points to location
  3072                              <1> 			     ; / in buffer in which to start writing data
  3073                              <1> 	; 19/07/2022
  3074                              <1> 	;  EDX = user data offset (previous value of [u.pbase])
  3075                              <1> 	;  ESI = pointer to file offset 
  3076                              <1> 	;  EDI = system (I/O) buffer offset
  3077                              <1> 	;  ECX = byte count
  3078                              <1> 	;  EBX = system buffer (data) address	
  3079                              <1> 	;  EAX = remain bytes after byte count within page frame 
  3080                              <1> 
  3081                              <1> 	; 19/07/2022 - Erdogan Tan
  3082                              <1> 	; BugFix (Also original unix v1 kernel code has this bug!)
  3083                              <1> 	; ((Against a possible disk write failure/error, 
  3084                              <1> 	;   file offset must not be updated/increased before 'dskwr'
  3085                              <1> 	;   but it was updated in 'sioreg'. I have modified 'sioreg'
  3086                              <1> 	;   and 'dskw' procedures for that.))
  3087                              <1> 
  3088                              <1> 	; 19/07/2022
  3089 00004DC9 56                  <1> 	push	esi ; *	 ; save file offset (pointer)
  3090 00004DCA 51                  <1> 	push	ecx ; ** ; save byte count
  3091 00004DCB 89D6                <1> 	mov	esi, edx
  3092                              <1> 
  3093                              <1> 	; ESI = file (user data) offset
  3094                              <1> 	; EDI = sector (I/O) buffer offset
  3095                              <1> 	; ECX = byte count
  3096                              <1> 	;
  3097 00004DCD F3A4                <1>   	rep	movsb
  3098                              <1> 		; movb (r1 )+,(r2)+ 
  3099                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3100                              <1> 		; dec r3 / decrement no. of bytes to be written
  3101                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3102                              <1> 	; 25/07/2015
  3103                              <1> 	; eax = remain bytes in buffer
  3104                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3105 00004DCF 09C0                <1> 	or	eax, eax
  3106 00004DD1 75EC                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  3107                              <1> dskw_6:
  3108 00004DD3 E85A060000          <1> 	call	dskwr
  3109                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3110                              <1> 
  3111                              <1> 	; 19/07/2022
  3112                              <1> 	; (there is not a disk write error, we can increase file offset)
  3113 00004DD8 58                  <1> 	pop	eax ; ** ; byte count
  3114 00004DD9 5F                  <1> 	pop	edi ; *  ; file offset (pointer)
  3115                              <1> 	;
  3116 00004DDA 0107                <1> 	add	[edi], eax
  3117                              <1> 			; new file offset (old offset + byte count)
  3118                              <1> 
  3119 00004DDC 833D[24650000]00    <1>         cmp     dword [u.count], 0
  3120                              <1> 		; tst u.count / any more data to write?
  3121 00004DE3 779C                <1> 	ja	short dskw_1
  3122                              <1> 		; bne 1b / yes, branch
  3123                              <1> 	; 03/08/2013
  3124 00004DE5 C605[61650000]00    <1> 	mov	byte [u.kcall], 0
  3125                              <1> 	; 20/09/2013 (;;)
  3126                              <1> 	;pop	ax
  3127                              <1> 	; 03/02/2022
  3128 00004DEC 58                  <1> 	pop	eax
  3129 00004DED C3                  <1> 	retn
  3130                              <1> 	;;jmp 	short dskw_ret 
  3131                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3132                              <1> 
  3133                              <1> cpass: ; / get next character from user area of core and put it in r1
  3134                              <1> 	; 18/10/2015
  3135                              <1> 	; 10/10/2015
  3136                              <1> 	; 10/07/2015
  3137                              <1> 	; 02/07/2015
  3138                              <1> 	; 01/07/2015
  3139                              <1> 	; 24/06/2015
  3140                              <1> 	; 08/06/2015
  3141                              <1> 	; 04/06/2015
  3142                              <1> 	; 20/05/2015
  3143                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3144                              <1> 	;
  3145                              <1> 	; INPUTS -> 
  3146                              <1> 	;     [u.base] = virtual address in user area
  3147                              <1> 	;     [u.count] = byte count (max.)
  3148                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3149                              <1> 	; OUTPUTS -> 
  3150                              <1> 	;     AL = the character which is pointed by [u.base]
  3151                              <1> 	;     zf = 1 -> transfer count has been completed	
  3152                              <1>         ;
  3153                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  3154                              <1> 	;
  3155                              <1> 	;
  3156 00004DEE 833D[24650000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3157                              <1> 		; tst u.count / have all the characters been transferred
  3158                              <1> 			    ; / (i.e., u.count, # of chars. left
  3159 00004DF5 763F                <1> 	jna	short cpass_3
  3160                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3161 00004DF7 FF0D[24650000]      <1> 	dec	dword [u.count]
  3162                              <1> 		; dec u.count / no, decrement u.count
  3163                              <1>         ; 19/05/2015 
  3164                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3165                              <1> 	;		      to physical address
  3166 00004DFD 66833D[5F650000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3167                              <1> 			     ; 1-4095 --> use previous physical base address
  3168                              <1> 			     ; in [u.pbase]
  3169 00004E05 770E                <1> 	ja	short cpass_1
  3170                              <1> 	; 02/07/2015
  3171 00004E07 833D[57650000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  3172 00004E0E 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  3173                              <1> 	; 08/06/2015 - 10/07/2015
  3174 00004E10 E84AFDFFFF          <1> 	call	trans_addr_r
  3175                              <1> cpass_1:
  3176                              <1> 	; 02/07/2015
  3177                              <1> 	; 24/06/2015
  3178 00004E15 66FF0D[5F650000]    <1> 	dec	word [u.pcount]
  3179                              <1> cpass_2: 
  3180                              <1> 	; 10/10/2015
  3181                              <1> 	; 02/07/2015
  3182 00004E1C 8B15[5B650000]      <1> 	mov	edx, [u.pbase]
  3183 00004E22 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3184                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3185                              <1> 				; / by u.base and put it in r1
  3186 00004E24 FF05[28650000]      <1> 	inc	dword [u.nread]
  3187                              <1> 		; inc u.nread / increment no. of bytes transferred
  3188 00004E2A FF05[20650000]      <1> 	inc	dword [u.base]
  3189                              <1> 		; inc u.base / increment the buffer address to point to the
  3190                              <1> 			   ; / next byte
  3191 00004E30 FF05[5B650000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3192                              <1> cpass_3:
  3193 00004E36 C3                  <1> 	retn
  3194                              <1> 		; rts	r0 / next byte
  3195                              <1> 	; 1: 
  3196                              <1> 		; mov (sp)+,r0 
  3197                              <1> 		         ; / put return address of calling routine into r0
  3198                              <1> 		; mov (sp)+,r1 / i-number in r1
  3199                              <1> 		; rts r0 / non-local return
  3200                              <1> cpass_k:
  3201                              <1> 	; 02/07/2015
  3202                              <1> 	; The caller is os kernel 
  3203                              <1> 	; (get sysexec arguments from kernel's memory space)
  3204                              <1> 	;
  3205 00004E37 8B1D[20650000]      <1> 	mov	ebx, [u.base]
  3206 00004E3D 66C705[5F650000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3206 00004E45 10                  <1>
  3207 00004E46 891D[5B650000]      <1> 	mov	[u.pbase], ebx
  3208 00004E4C EBCE                <1> 	jmp	short cpass_2
  3209                              <1> 	
  3210                              <1> sioreg: 
  3211                              <1> 	; 19/07/2022
  3212                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  3213                              <1> 	; 25/07/2015
  3214                              <1> 	; 18/07/2015
  3215                              <1> 	; 02/07/2015
  3216                              <1> 	; 17/06/2015
  3217                              <1> 	; 09/06/2015
  3218                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3219                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3220                              <1> 	;
  3221                              <1> 	; INPUTS -> 
  3222                              <1> 	;     EBX = system buffer (data) address (r5)
  3223                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3224                              <1> 	;     [u.base] = virtual address of the user buffer
  3225                              <1> 	;     [u.pbase] = physical address of the user buffer
  3226                              <1> 	;     [u.count] = byte count
  3227                              <1> 	;     [u.pcount] = byte count within page frame 			
  3228                              <1> 	; OUTPUTS -> 
  3229                              <1> 	;     ESI = user data offset (r1)
  3230                              <1> 	;     EDI = system (I/O) buffer offset (r2)
  3231                              <1> 	;     ECX = byte count (r3)
  3232                              <1> 	;     EAX = remain bytes after byte count within page frame
  3233                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3234                              <1>         ;
  3235                              <1> 	; ((Modified registers:  EDX))
  3236                              <1> 
  3237                              <1> 	; 19/07/2022
  3238                              <1> 	; OUTPUTS -> 
  3239                              <1> 	;	EDX = user data offset (previous value of [u.pbase])
  3240                              <1> 	;	ESI = pointer to file offset 
  3241                              <1> 	; 	EDI = system (I/O) buffer offset
  3242                              <1> 	;	ECX = byte count
  3243                              <1> 	;	EBX = system buffer (data) address	
  3244                              <1> 	;	EAX = remain bytes after byte count within page frame 
  3245                              <1> 
  3246 00004E4E 8B35[10650000]      <1>         mov     esi, [u.fofp]
  3247 00004E54 8B3E                <1>         mov     edi, [esi]
  3248                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3249 00004E56 89F9                <1> 	mov	ecx, edi
  3250                              <1> 		; mov r2,r3 / and also to r3
  3251 00004E58 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3252                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3253 00004E5E 81E7FF010000        <1> 	and	edi, 1FFh
  3254                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3255 00004E64 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3256                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3257                              <1> 			  ; / where data is to be placed
  3258                              <1>                 ; mov u.base,r1 / address of data is in r1
  3259 00004E66 F7D9                <1> 	neg	ecx
  3260                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3261                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3262 00004E68 3B0D[24650000]      <1> 	cmp	ecx, [u.count]
  3263                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3264                              <1> 			       ; / to be written to the file
  3265 00004E6E 7606                <1> 	jna	short sioreg_0
  3266                              <1> 		; blos 2f / if less than branch. Use the no. of free bytes
  3267                              <1> 			 ; / in the file block as the number to be written
  3268 00004E70 8B0D[24650000]      <1> 	mov	ecx, [u.count]
  3269                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3270                              <1> 			       ; / bytes as the number to be written
  3271                              <1> sioreg_0:
  3272                              <1> 	; 17/06/2015
  3273 00004E76 803D[61650000]00    <1> 	cmp	byte [u.kcall], 0 
  3274 00004E7D 7613                <1> 	jna	short sioreg_1
  3275                              <1> 	; 25/07/2015
  3276                              <1> 	; the caller is 'mkdir' or 'namei'
  3277 00004E7F A1[20650000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3278 00004E84 A3[5B650000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3279 00004E89 66890D[5F650000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3280 00004E90 EB0B                <1> 	jmp	short sioreg_2
  3281                              <1> sioreg_1:
  3282                              <1> 	; 25/07/2015
  3283                              <1> 	; 18/07/2015
  3284                              <1> 	; 09/06/2015 
  3285 00004E92 0FB715[5F650000]    <1> 	movzx	edx, word [u.pcount]
  3286                              <1> 		; ecx and [u.pcount] are always > 0, here
  3287 00004E99 39D1                <1> 	cmp	ecx, edx	
  3288 00004E9B 7728                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3289                              <1> sioreg_2: ; 2:
  3290 00004E9D 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3291                              <1> sioreg_3:
  3292 00004E9F 010D[28650000]      <1> 	add 	[u.nread], ecx
  3293                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3294                              <1> 			         ; / during write is put into u.nread
  3295 00004EA5 290D[24650000]      <1> 	sub 	[u.count], ecx
  3296                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3297                              <1> 			       ; / must be written or read
  3298 00004EAB 010D[20650000]      <1> 	add 	[u.base], ecx
  3299                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3300                              <1> 			      ; / data bytes
  3301                              <1>         ; 19/07/2022
  3302                              <1> 	;add 	[esi], ecx 
  3303                              <1> 	;	; add r3,*u.fofp / new file offset = number of bytes done
  3304                              <1> 			       ; / + old file offset
  3305                              <1> 	; 25/07/2015
  3306                              <1> 	;mov	esi, [u.pbase]
  3307                              <1> 	; 19/07/2022
  3308 00004EB1 8B15[5B650000]      <1> 	mov	edx, [u.pbase]
  3309                              <1> 
  3310 00004EB7 66290D[5F650000]    <1> 	sub	[u.pcount], cx
  3311 00004EBE 010D[5B650000]      <1> 	add	[u.pbase], ecx
  3312 00004EC4 C3                  <1>         retn
  3313                              <1> 		; rts r0
  3314                              <1> 		; transfer count > [u.pcount]
  3315                              <1> sioreg_4:
  3316                              <1> 	; 25/07/2015
  3317                              <1> 	; transfer count > [u.pcount] 
  3318                              <1> 	; (ecx > edx)
  3319 00004EC5 89C8                <1> 	mov	eax, ecx
  3320 00004EC7 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3321 00004EC9 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3322 00004ECB EBD2                <1> 	jmp	short sioreg_3
  2058                                  %include 'u7.s'        ; 18/04/2015
  2059                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS7.INC
  2060                              <1> ; Last Modification: 13/06/2022
  2061                              <1> ; ----------------------------------------------------------------------------
  2062                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2063                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2064                              <1> ;
  2065                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2066                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2067                              <1> ; <Bell Laboratories (17/3/1972)>
  2068                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2069                              <1> ;
  2070                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2071                              <1> ;
  2072                              <1> ; ****************************************************************************
  2073                              <1> ; 14/11/2015
  2074                              <1> 
  2075                              <1> sysmount: ; / mount file system; args special; name
  2076                              <1> 	; 14/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2077                              <1> 	; 12/02/2022
  2078                              <1> 	; 04/02/2022
  2079                              <1> 	; 14/11/2015
  2080                              <1> 	; 24/10/2015
  2081                              <1> 	; 13/10/2015
  2082                              <1> 	; 10/07/2015
  2083                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2084                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2085                              <1> 	;
  2086                              <1> 	; 'sysmount' anounces to the system that a removable 
  2087                              <1> 	; file system has been mounted on a special file.
  2088                              <1> 	; The device number of the special file is obtained vihha
  2089                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2090                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2091                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2092                              <1> 	; to read file system into core, i.e. the first block on the
  2093                              <1> 	; mountable file system is read in. This block is super block
  2094                              <1> 	; for the file system. This call is super user restricted.	
  2095                              <1> 	;
  2096                              <1> 	; Calling sequence:
  2097                              <1> 	;	sysmount; special; name
  2098                              <1> 	; Arguments:
  2099                              <1> 	;	special - pointer to name of special file (device)
  2100                              <1> 	;	name -  pointer to name of the root directory of the
  2101                              <1> 	;		newly mounted file system. 'name' should 
  2102                              <1> 	;		always be a directory.
  2103                              <1> 	; Inputs: - 
  2104                              <1> 	; Outputs: -
  2105                              <1> 	; ...............................................................
  2106                              <1> 	;				
  2107                              <1> 	; Retro UNIX 8086 v1 modification: 
  2108                              <1> 	;       'sysmount' system call has two arguments; so,
  2109                              <1> 	;	* 1st argument, special is pointed to by BX register
  2110                              <1> 	;	* 2nd argument, name is in CX register
  2111                              <1> 	;
  2112                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2113                              <1> 	;	       already modified for IBM PC compatibility and 
  2114                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2115                              <1> 	
  2116                              <1> 	;call	arg2
  2117                              <1> 		; jsr r0,arg2 / get arguments special and name
  2118 00004ECD 891D[18650000]      <1> 	mov	[u.namep], ebx
  2119                              <1> 	; 12/02/2022
  2120                              <1> 	;push	ecx ; directory name
  2121 00004ED3 66833D[E8640000]00  <1> 	cmp	word [mnti], 0
  2122                              <1> 		; tst mnti / is the i-number of the cross device file
  2123                              <1> 			 ; / zero?
  2124                              <1> 	;;ja	error
  2125                              <1>         	; bne errora / no, error
  2126                              <1> 	;ja	sysmnt_err0
  2127                              <1> 	; 04/02/2022
  2128 00004EDB 7605                <1> 	jna	short sysmnt_0
  2129 00004EDD E950010000          <1> 	jmp	sysmnt_err0
  2130                              <1> sysmnt_0:
  2131                              <1> 	; 12/02/2022
  2132 00004EE2 51                  <1> 	push	ecx ; directory name
  2133 00004EE3 E859010000          <1> 	call	getspl
  2134                              <1> 		; jsr r0,getspl / get special files device number in r1
  2135                              <1> 	; 12/02/2022
  2136 00004EE8 8F05[18650000]      <1> 	pop	dword [u.namep] ; directory name
  2137                              <1> 	; 13/10/2015
  2138                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2139                              <1> 	; 04/02/2022
  2140 00004EEE 29DB                <1> 	sub	ebx, ebx
  2141 00004EF0 88C3                <1> 	mov	bl, al
  2142 00004EF2 F683[7E5C0000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2143 00004EF9 750F                <1> 	jnz	short sysmnt_1
  2144                              <1> sysmnt_err1:
  2145 00004EFB C705[4F650000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2145 00004F03 0000                <1>
  2146 00004F05 E9D7E1FFFF          <1> 	jmp	error
  2147                              <1> sysmnt_1:
  2148                              <1> 	; 12/02/2022
  2149                              <1> 	;pop	dword [u.namep]
  2150                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2151                              <1> 				  ; / on the device
  2152                              <1> 	; 14/11/2015
  2153 00004F0A 53                  <1> 	push	ebx ; 13/10/2015
  2154                              <1> 		; mov r1,-(sp) / save the device number
  2155                              <1>         ;
  2156 00004F0B E8D1F0FFFF          <1> 	call	namei
  2157                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2158                              <1> 		       ; ax = 0 -> file not found 	
  2159                              <1> 	;jz	error
  2160                              <1> 	;jc	error
  2161                              <1> 		; jsr r0,namei / get the i-number of the file
  2162                              <1>                	; br errora
  2163 00004F10 730F                <1> 	jnc	short sysmnt_2
  2164                              <1> sysmnt_err2:
  2165 00004F12 C705[4F650000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2165 00004F1A 0000                <1>
  2166 00004F1C E9C0E1FFFF          <1> 	jmp	error
  2167                              <1> sysmnt_2:	
  2168 00004F21 66A3[E8640000]      <1> 	mov	[mnti], ax
  2169                              <1>         	; mov r1,mnti / put it in mnti
  2170                              <1> 
  2171                              <1> 	; 14/05/2022
  2172                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2173 00004F27 66A1[E0640000]      <1> 	mov	ax, [ii]
  2174 00004F2D 66A3[EA640000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2175                              <1> 
  2176                              <1> 	; 04/02/2022
  2177 00004F33 BB[C8770000]        <1> 	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2178                              <1> sysmnt_3: ;1:
  2179                              <1>         ;cmp	byte [ebx+1], 0
  2180                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2181                              <1> 			   ; / dismountable device set?
  2182                              <1>         ;jna	short sysmnt_4		
  2183                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2184                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2185                              <1> 	;jmp	short sysmnt_3
  2186                              <1> sysmnt_4:   
  2187 00004F38 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2188 00004F39 A2[E7640000]        <1> 	mov	[mdev], al
  2189                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2190 00004F3E 8803                <1> 	mov	[ebx], al
  2191                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2192                              <1> 			      ; / of the I/O queue entry
  2193                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2194                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2195 00004F40 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2196                              <1> 		; bis $2000,sb1 / set the read bit
  2197                              <1> 	; Retro UNIX 386 v1 modification : 
  2198                              <1> 	;	32 bit block number at buffer header offset 4
  2199 00004F45 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2200 00004F4C E8AB050000          <1> 	call 	diskio
  2201 00004F51 7345                <1> 	jnc	short sysmnt_5
  2202 00004F53 31C0                <1> 	xor 	eax, eax
  2203 00004F55 66A3[E8640000]      <1> 	mov	[mnti], ax ; 0
  2204 00004F5B A2[E7640000]        <1> 	mov	[mdev], al ; 0
  2205                              <1> 	;mov	[cdev], al ; 0
  2206                              <1> 	; 12/02/2022
  2207 00004F60 803D[62650000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2208 00004F67 7508                <1> 	jne	short sysmnt_err3
  2209                              <1> 	; yes, clear [u.brwdev] for next check
  2210                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2211 00004F69 FE05[62650000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2212 00004F6F EB0A                <1> 	jmp	short sysmnt_err4
  2213                              <1> sysmnt_err3:	; 12/02/2022
  2214                              <1> 	; no, set [u.error] to disk read error
  2215 00004F71 C705[4F650000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2215 00004F79 0000                <1>
  2216                              <1> sysmnt_err4:
  2217                              <1> 	; 12/02/2022
  2218                              <1> 	; 14/11/2015
  2219 00004F7B FEC8                <1> 	dec 	al
  2220 00004F7D 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2221 00004F7F FEC0                <1> 	inc	al
  2222 00004F81 48                  <1> 	dec	eax
  2223 00004F82 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2224 00004F85 E957E1FFFF          <1> 	jmp	error
  2225                              <1> sysmnt_invd:
  2226                              <1> 	; 12/02/2022
  2227 00004F8A C705[4F650000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2227 00004F92 0000                <1>
  2228                              <1> 				 ;'invalid fs/superblock !' error
  2229 00004F94 30C0                <1> 	xor	al, al
  2230 00004F96 EBE3                <1> 	jmp	short sysmnt_err4
  2231                              <1> 
  2232                              <1> sysmnt_5:
  2233                              <1> 	; 04/02/2022 (BugFix)
  2234                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2235                              <1> 	; (Following check is needed to prevent mounting an
  2236                              <1> 	; invalid valid file system (invalid super block).
  2237                              <1> 	; 
  2238 00004F98 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2239 00004F9B C0E002              <1> 	shl	al, 2 ; 4*index
  2240 00004F9E 8B88[625C0000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2241                              <1> 	;;shl 	ecx, 3 ; !!!
  2242                              <1> 	; 04/02/2022
  2243 00004FA4 C1E903              <1> 	shr 	ecx, 3 ; (8 sectors per 1 fbm byte)
  2244                              <1> 	; ecx = number of free map bytes (required)
  2245                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2246 00004FA7 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)
  2247                              <1> 	; ! Buffer header is 8 bytes (Retro UNIX 386 v1 and v1.1) !
  2248                              <1> 	;;movzx	edx, word [sb1+4] ; the 1st data word ; !!!
  2249 00004FAB 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2250                              <1> 			 ; (in sectors), if they are not equal
  2251                              <1> 			 ; the disk to be mounted is an...	
  2252 00004FAD 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2253                              <1> 			 ; (which has not got a valid super block)
  2254                              <1> 	;
  2255 00004FAF C6430100            <1> 	mov	byte [ebx+1], 0
  2256                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2257                              <1> ;sysmnt_6: ;1:
  2258                              <1> 	;;cmp	byte [sb1+1], 0
  2259                              <1> 		; tstb sb1+1 / done reading?
  2260                              <1>    	;;jna	sysret
  2261                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2262                              <1> 	;;jmp	short sysmnt_6
  2263                              <1> 		;bne 1b / no, wait
  2264                              <1>         	;br sysreta / yes
  2265 00004FB3 E949E1FFFF          <1> 	jmp	sysret
  2266                              <1> 
  2267                              <1> sysumount: ; / special dismount file system,
  2268                              <1> 	; 15/05/2022
  2269                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2270                              <1> 	; 04/02/2022
  2271                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2272                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2273                              <1> 	;
  2274                              <1> 	; 04/11/2013
  2275                              <1> 	; 09/07/2013
  2276                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2277                              <1> 	; indicated as an argument is no longer contain a removable
  2278                              <1> 	; file system. 'getspl' gets the device number of the special
  2279                              <1> 	; file. If no file system was mounted on that device an error
  2280                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2281                              <1> 	; to 'sysret'.
  2282                              <1> 	;
  2283                              <1> 	; Calling sequence:
  2284                              <1> 	;	sysmount; special
  2285                              <1> 	; Arguments:
  2286                              <1> 	;	special - special file to dismount (device)
  2287                              <1> 	;
  2288                              <1> 	; Inputs: - 
  2289                              <1> 	; Outputs: -
  2290                              <1> 	; ...............................................................
  2291                              <1> 	;				
  2292                              <1> 	; Retro UNIX 8086 v1 modification: 
  2293                              <1> 	;       'sysumount' system call has one argument; so,
  2294                              <1> 	;	* Single argument, special is pointed to by BX register
  2295                              <1> 	;
  2296                              <1> 	
  2297                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2298                              <1> 	;call	arg
  2299                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2300 00004FB8 891D[18650000]      <1>         mov	[u.namep], ebx
  2301 00004FBE E87E000000          <1> 	call	getspl
  2302                              <1> 		; jsr r0,getspl / get the device number in r1
  2303                              <1> 	;;;
  2304                              <1> 	; 09/05/2022 - Erdogan Tan
  2305                              <1> 	; (I have added [mnti] check because
  2306                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2307                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2308                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2309                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2310 00004FC3 66833D[E8640000]00  <1> 	cmp	word [mnti], 0
  2311 00004FCB 7665                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2312                              <1> 	;;;
  2313                              <1> 
  2314 00004FCD 3A05[E7640000]      <1> 	cmp	al, [mdev]
  2315                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2316 00004FD3 755D                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2317                              <1> 	;jne	error
  2318                              <1>         	; bne errora / no error
  2319 00004FD5 30C0                <1> 	xor	al, al ; ah = 0
  2320                              <1> sysumnt_0: ;1:
  2321                              <1>      	; 04/02/2022
  2322                              <1> 	;cmp 	[sb1+1], al ; 0
  2323                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2324                              <1> 	;		   ; / (inhibit bit set)?
  2325                              <1> 	;jna	short sysumnt_1		
  2326                              <1> 	;	; bne 1b / yes, wait
  2327                              <1> 	;call	idle ; (wait for hardware interrupt)
  2328                              <1> 	;jmp	short sysumnt_0
  2329                              <1> sysumnt_1:
  2330                              <1> 	; 15/05/2022
  2331                              <1> 	; change user's current directory to mounting directory
  2332                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2333 00004FD7 3805[44650000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2334 00004FDD 7643                <1> 	jna	short sysumnt_4
  2335                              <1> 	;;;
  2336                              <1> 	; 15/05/2022
  2337                              <1> 	; It is needed to change the parent process's current
  2338                              <1> 	; directory because shell runs (/etc/umount) 
  2339                              <1> 	; as child process.
  2340 00004FDF 31DB                <1> 	xor	ebx, ebx 
  2341 00004FE1 8A1D[49650000]      <1> 	mov	bl, [u.uno]
  2342 00004FE7 D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2343 00004FE9 81C3[32620000]      <1> 	add	ebx, p.ppid-2
  2344 00004FEF 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2345 00004FF2 BE[14620000]        <1> 	mov	esi, p.pid
  2346 00004FF7 29C9                <1> 	sub	ecx, ecx
  2347 00004FF9 B110                <1> 	mov	cl, nproc ; 16  
  2348                              <1> sysumnt_2:	
  2349 00004FFB 66AD                <1> 	lodsw
  2350 00004FFD 6639D0              <1> 	cmp	ax, dx
  2351 00005000 7402                <1> 	je	short sysumnt_3
  2352 00005002 E2F7                <1> 	loop	sysumnt_2
  2353                              <1> sysumnt_3:
  2354 00005004 31C0                <1> 	xor	eax, eax
  2355 00005006 81EE[14620000]      <1> 	sub	esi, p.pid
  2356 0000500C D1E6                <1> 	shl	esi, 1
  2357 0000500E 8B9E[80620000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2358                              <1> 	; ebx points to user (u) structure in upage
  2359 00005014 668B15[E8640000]    <1> 	mov	dx, [mnti]
  2360                              <1> 	;mov	[u.cdir], dx
  2361                              <1> 	;mov	[u.cdrv], al ; 0
  2362 0000501B 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2363 0000501F 88434C              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2364                              <1> 	;;;
  2365                              <1> sysumnt_4: 
  2366 00005022 A2[E7640000]        <1> 	mov	[mdev], al ; 0
  2367                              <1> 	     	; clr mntd / no, clear these
  2368 00005027 66A3[E8640000]      <1>    	mov	[mnti], ax ; 0
  2369                              <1>         	; clr mnti
  2370                              <1> 
  2371                              <1> 	;; 15/05/2022
  2372                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2373                              <1> 	;mov	ax, dx  ; [u.cdir]
  2374                              <1> 	;call	iget		
  2375                              <1> 
  2376 0000502D E9CFE0FFFF          <1>         jmp	sysret
  2377                              <1> 		; br sysreta / return
  2378                              <1> 
  2379                              <1> sysmnt_err0:
  2380 00005032 C705[4F650000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2380 0000503A 0000                <1>
  2381 0000503C E9A0E0FFFF          <1> 	jmp	error
  2382                              <1> 
  2383                              <1> getspl: ; / get device number from a special file name
  2384 00005041 E89BEFFFFF          <1> 	call	namei
  2385                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2386                              <1> 		       ; ax = 0 -> file not found 	
  2387                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2388                              <1> 	; 04/02/2022
  2389 00005046 7305                <1> 	jnc	short getspl_0
  2390 00005048 E9C5FEFFFF          <1> 	jmp	sysmnt_err2
  2391                              <1> getspl_0:
  2392                              <1> 	;jz	error
  2393                              <1> 	;jc	error
  2394                              <1> 		; jsr r0,namei / get the i-number of the special file
  2395                              <1>                 ; br errora / no such file
  2396 0000504D 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2397                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2398                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2399 00005051 72DF                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2400                              <1> 	;jc	error
  2401                              <1> 		; ble errora / less than 0?  yes, error
  2402 00005053 6683F805            <1>         cmp	ax, 5 ;
  2403                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2404                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2405                              <1> 	;;ja	error
  2406                              <1>         ;	; bgt errora / yes, error
  2407                              <1>         ; 04/02/2022
  2408 00005057 7600                <1> 	jna	short getspl_retn
  2409                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2410                              <1> ;iopen_retn:
  2411                              <1> ;	retn
  2412                              <1> 		; rts r0 / return with device number in r1
  2413                              <1> ;sysmnt_err0:
  2414                              <1> ;	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2415                              <1> ;	jmp	error
  2416                              <1> 
  2417                              <1> getspl_retn:
  2418                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2419                              <1> 	; 04/02/2022
  2420                              <1> iopen_retn:
  2421 00005059 C3                  <1> 	retn
  2422                              <1> 
  2423                              <1> iopen:
  2424                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2425                              <1> 	;		(Printer initialization)
  2426                              <1> 	; 04/02/2022
  2427                              <1> 	; 19/05/2015
  2428                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2429                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2430                              <1> 	;
  2431                              <1> 	; open file whose i-number is in r1
  2432                              <1> 	; 
  2433                              <1> 	; INPUTS ->
  2434                              <1> 	;    r1 - inode number
  2435                              <1> 	; OUTPUTS ->
  2436                              <1> 	;    file's inode in core	
  2437                              <1> 	;    r1 - inode number (positive)
  2438                              <1> 	;
  2439                              <1> 	; ((AX = R1))
  2440                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2441                              <1> 	;        
  2442                              <1> ; / open file whose i-number is in r1
  2443 0000505A F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2444                              <1> 		; tst r1 / write or read access?
  2445 0000505D 7568                <1>         jnz	short iopen_2
  2446                              <1> 		; blt 2f / write, go to 2f
  2447 0000505F B202                <1> 	mov	dl, 2 ; read access
  2448 00005061 E864F8FFFF          <1> 	call	access
  2449                              <1>         	; jsr r0,access; 2 
  2450                              <1> 	; / get inode into core with read access
  2451                              <1> 	; DL=2
  2452                              <1> iopen_0:
  2453 00005066 6683F828            <1>         cmp	ax, 40
  2454                              <1> 		; cmp r1,$40. / is it a special file
  2455 0000506A 77ED                <1>         ja	short iopen_retn
  2456                              <1> 		; bgt 3f / no. 3f
  2457                              <1> 	; 04/02/2022
  2458 0000506C 50                  <1> 	push	eax
  2459                              <1> 	;push	ax
  2460                              <1> 		; mov r1,-(sp) / yes, figure out
  2461 0000506D 0FB6D8              <1> 	movzx	ebx, al
  2462 00005070 C0E302              <1> 	shl	bl, 2 ; * 4 ; 04/02/2022
  2463                              <1> 	;shl	bx, 2
  2464                              <1> 		; asl r1
  2465 00005073 81C3[77500000]      <1>         add     ebx, iopen_1 - 4
  2466 00005079 FF23                <1> 	jmp	dword [ebx]
  2467                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2468                              <1> iopen_1: ; 1:
  2469 0000507B [DF500000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2470                              <1>  		 ;otty / tty ; r1=2
  2471                              <1>         	 ;oppt / ppt ; r1=4
  2472 0000507F [97510000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2473                              <1> 		 ;sret / mem ; r1=6
  2474                              <1> 		 ;sret / rf0
  2475                              <1>         	 ;sret / rk0
  2476                              <1>         	 ;sret / tap0
  2477                              <1>         	 ;sret / tap1
  2478                              <1>         	 ;sret / tap2
  2479                              <1>         	 ;sret / tap3
  2480                              <1>         	 ;sret / tap4
  2481                              <1>         	 ;sret / tap5
  2482                              <1>         	 ;sret / tap6
  2483                              <1>         	 ;sret / tap7
  2484 00005083 [97510000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2485 00005087 [97510000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2486 0000508B [97510000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2487 0000508F [97510000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2488 00005093 [97510000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2489 00005097 [97510000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2490                              <1> 	;;dd	error ; lpr, AX = 9 (error !)
  2491                              <1>         ;dd	sret ; lpr, AX = 9 (runix)
  2492                              <1> 	; 13/06/2022 - (lpt_init)
  2493 0000509B [63520000]          <1>         dd	ejec ; lpr, AX = 9 (runix)
  2494 0000509F [F0500000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2495                              <1> 		 ;ocvt / tty0
  2496 000050A3 [F0500000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2497                              <1> 		 ;ocvt / tty1
  2498 000050A7 [F0500000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2499                              <1> 		 ;ocvt / tty2
  2500 000050AB [F0500000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2501                              <1> 		 ;ocvt / tty3
  2502 000050AF [F0500000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2503                              <1> 		 ;ocvt / tty4
  2504 000050B3 [F0500000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2505                              <1> 		 ;ocvt / tty5
  2506 000050B7 [F0500000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2507                              <1> 		 ;ocvt / tty6
  2508 000050BB [F0500000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2509                              <1> 		 ;ocvt / tty7
  2510 000050BF [F0500000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2511                              <1> 		 ;error / crd
  2512 000050C3 [F0500000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2513                              <1> 
  2514                              <1> iopen_2: ; 2: / check open write access
  2515 000050C7 66F7D8              <1> 	neg	ax
  2516                              <1> 		; neg r1 / make inode number positive
  2517 000050CA B201                <1> 	mov	dl, 1 ; write access
  2518 000050CC E8F9F7FFFF          <1> 	call	access
  2519                              <1> 		; jsr r0,access; 1 / get inode in core
  2520                              <1> 	; DL=1
  2521                              <1> 	; 04/02/2022
  2522 000050D1 F605[F5610000]40    <1> 	test	byte [i.flgs+1], 40h
  2523                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2524                              <1>  		; bit $40000,i.flgs / is it a directory?
  2525 000050D8 748C                <1> 	jz	short iopen_0
  2526                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2527                              <1> 	;jmp	error ; permission denied !
  2528 000050DA E953FFFFFF          <1> 	jmp	sysmnt_err0
  2529                              <1> 	;;jnz	error		
  2530                              <1>        		; bne 2f / yes, transfer (error)
  2531                              <1>         ;;jmp	short iopen_0
  2532                              <1> 	;cmp	ax, 40
  2533                              <1> 		; cmp r1,$40. / no, is it a special file?
  2534                              <1>         ;ja	short iopen_2
  2535                              <1> 		; bgt 3f / no, return
  2536                              <1> 	;push	ax
  2537                              <1> 		; mov r1,-(sp) / yes
  2538                              <1> 	;movzx	ebx, al
  2539                              <1> 	;shl	bx, 1
  2540                              <1> 		; asl r1
  2541                              <1> 	;add	ebx, ipen_3 - 2
  2542                              <1> 	;jmp	dword [ebx]
  2543                              <1> 		; jmp *1f-2(r1) / figure out 
  2544                              <1> 			; / which special file it is and transfer
  2545                              <1> ;iopen_3: ; 1:
  2546                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2547                              <1>  		 ;otty / tty ; r1=2
  2548                              <1>         	 ;leadr / ppt ; r1=4
  2549                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2550                              <1> 		 ;sret / mem ; r1=6
  2551                              <1> 		 ;sret / rf0
  2552                              <1>         	 ;sret / rk0
  2553                              <1>         	 ;sret / tap0
  2554                              <1>         	 ;sret / tap1
  2555                              <1>         	 ;sret / tap2
  2556                              <1>         	 ;sret / tap3
  2557                              <1>         	 ;sret / tap4
  2558                              <1>         	 ;sret / tap5
  2559                              <1>         	 ;sret / tap6
  2560                              <1>         	 ;sret / tap7
  2561                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2562                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2563                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2564                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2565                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2566                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2567                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2568                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2569                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2570                              <1> 		 ;ocvt / tty0
  2571                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2572                              <1> 		 ;ocvt / tty1
  2573                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2574                              <1> 		 ;ocvt / tty2
  2575                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2576                              <1> 		 ;ocvt / tty3
  2577                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2578                              <1> 		 ;ocvt / tty4
  2579                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2580                              <1> 		 ;ocvt / tty5
  2581                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2582                              <1> 		 ;ocvt / tty6
  2583                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2584                              <1> 		 ;ocvt / tty7
  2585                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2586                              <1> 		 ;/ ejec / lpr
  2587                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2588                              <1> 
  2589                              <1> otty: ;/ open console tty for reading or writing
  2590                              <1> 	; 03/03/2022
  2591                              <1> 	; 02/03/2022
  2592                              <1> 	; 27/02/2022
  2593                              <1> 	; 23/02/2022
  2594                              <1> 	; 22/02/2022
  2595                              <1> 	; 04/02/2022
  2596                              <1> 	; 16/11/2015
  2597                              <1> 	; 12/11/2015
  2598                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2599                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2600                              <1> 	; 16/07/2013
  2601                              <1> 	; Retro UNIX 8086 v1 modification:
  2602                              <1> 	;  If a tty is open for read or write by
  2603                              <1> 	;     a process (u.uno), only same process can open
  2604                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2605                              <1> 	;
  2606                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2607                              <1> 	;
  2608 000050DF 0FB61D[49650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2609 000050E6 8A83[53620000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2610                              <1> 	; 13/01/2014
  2611                              <1> 	;jmp	short ottyp
  2612                              <1> 	; 23/02/2022
  2613 000050EC 88C4                <1> 	mov	ah, al
  2614 000050EE EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2615                              <1> ocvt:
  2616 000050F0 2C0A                <1> 	sub	al, 10
  2617                              <1> 	; 04/02/2022
  2618 000050F2 31DB                <1> 	xor	ebx, ebx
  2619                              <1> ottyp:
  2620                              <1> 	; 23/02/2022
  2621 000050F4 B4FF                <1> 	mov	ah, 0FFh
  2622                              <1> ottypc:
  2623                              <1> 	; 03/03/2022
  2624                              <1> 	; 23/02/2022
  2625                              <1> 	; 22/02/2022
  2626                              <1> 	; 12/02/2022
  2627                              <1> 	; 04/02/2022
  2628                              <1> 	; 16/11/2015
  2629                              <1> 	; 12/11/2015
  2630                              <1> 	; 18/05/2015 (32 bit modifications)
  2631                              <1> 	; 06/12/2013 - 13/07/2014
  2632 000050F6 88C6                <1> 	mov	dh, al ; tty number
  2633                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2634                              <1> 	; 04/02/2022
  2635 000050F8 88C3                <1> 	mov	bl, al
  2636 000050FA D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2637                              <1> 	; 26/01/2014	
  2638 000050FC 81C3[84610000]      <1> 	add 	ebx, ttyl
  2639 00005102 668B0B              <1> 	mov 	cx, [ebx]
  2640                              <1> 		   ; CL = lock value (0 or process number)
  2641                              <1> 		   ; CH = open count 
  2642 00005105 20C9                <1> 	and 	cl, cl
  2643                              <1> 	; 13/01/2014
  2644                              <1> 	;jz 	short otty_ret
  2645                              <1> 	; 04/02/2022
  2646 00005107 7447                <1> 	jz 	short ottys_0
  2647                              <1> 	;
  2648                              <1> 	; 16/11/2015
  2649 00005109 3A0D[49650000]      <1> 	cmp 	cl, [u.uno]
  2650 0000510F 746E                <1> 	je	short ottys_3
  2651                              <1> 	;
  2652                              <1> 	; 23/02/2022
  2653                              <1> 	; (is it the console tty of the current process?)
  2654                              <1> 	; ((fast check/permit for console tty open function))
  2655 00005111 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2656 00005113 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2657                              <1> 	;
  2658                              <1> 	; 22/02/2022
  2659                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2660                              <1> 	;shl 	bl, 1
  2661                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2662                              <1> 	;;movzx ebx, byte [u.uno]
  2663                              <1> 	;mov	bl, [u.uno]
  2664                              <1> 	;shl 	bl, 1
  2665                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2666                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2667                              <1> 	; 22/02/2022 (BugFix) ; *
  2668 00005115 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2669 00005118 D1E6                <1> 	shl 	esi, 1
  2670 0000511A 668B86[12620000]    <1> 	mov 	ax, [esi+p.pid-2]
  2671 00005121 96                  <1> 	xchg	esi, eax
  2672 00005122 A0[49650000]        <1> 	mov	al, [u.uno]
  2673 00005127 D0E0                <1> 	shl 	al, 1
  2674 00005129 663BB0[32620000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2675 00005130 744D                <1> 	je 	short ottys_3 ; *
  2676                              <1> 	; 23/02/2022
  2677                              <1> 	; check console tty of the process
  2678                              <1> 	; (open permission must be given if the -requested- tty is
  2679                              <1> 	;  console tty of current process)
  2680 00005132 D0E8                <1> 	shr	al, 1
  2681 00005134 38B0[53620000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2682 0000513A 7443                <1> 	je 	short ottys_3
  2683                              <1> 	;
  2684                              <1> 	; the tty is locked by another process
  2685                              <1> 	; except the parent process (p.ppid)
  2686                              <1>         ;
  2687                              <1> 	; 09/02/2022
  2688                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2689                              <1> 	;		; permission denied ! error
  2690                              <1> otty_err: ; 13/01/2014
  2691                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2692                              <1> 	;;jnz	error
  2693                              <1> 	; 04/02/2022
  2694                              <1> 	;jz	short otty_stc_retn
  2695                              <1> 	;jmp	error
  2696                              <1> 	; 12/02/2022
  2697 0000513C 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2698 0000513F 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2699                              <1> 	; iopen (dl=1 or dl=2)
  2700 00005141 C705[4F650000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2700 00005149 0000                <1>
  2701                              <1> 			; permission denied ! error
  2702 0000514B E991DFFFFF          <1> 	jmp	error
  2703                              <1> ;otty_stc_retn:
  2704                              <1> 	;stc
  2705                              <1> 	;retn
  2706                              <1> ottys_0:
  2707                              <1> 	; 04/02/2022
  2708                              <1> otty_ret: 
  2709                              <1> 	; 13/01/2014
  2710 00005150 80FE07              <1> 	cmp 	dh, 7
  2711 00005153 7624                <1> 	jna	short ottys_2
  2712                              <1> 	; 16/11/2015
  2713                              <1> com_port_check:
  2714 00005155 BE[A2610000]        <1> 	mov	esi, com1p
  2715 0000515A 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2716 0000515D 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2717 0000515F 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2718                              <1> ottys_1:
  2719                              <1> 	; 12/11/2015
  2720 00005160 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2721 00005163 7714                <1> 	ja	short com_port_ready
  2722                              <1> 	;
  2723                              <1> 	; 12/02/2022
  2724 00005165 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2725 00005168 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2726 0000516A C705[4F650000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2726 00005172 0000                <1>
  2727                              <1> 			   ; device not ready ! error
  2728                              <1> 	;jmp	short otty_err
  2729 00005174 E968DFFFFF          <1> 	jmp	error
  2730                              <1> com_port_ready:
  2731                              <1> ottys_2:
  2732                              <1> 	; 02/03/2022
  2733                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2734                              <1> 	;jnz	short ottys_3
  2735 00005179 8A0D[49650000]      <1> 	mov	cl, [u.uno]
  2736                              <1> ottys_3:
  2737 0000517F FEC5                <1> 	inc 	ch
  2738 00005181 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2739                              <1> 	; 06/12/2013
  2740 00005184 FEC6                <1> 	inc	dh	; tty number + 1
  2741 00005186 BB[30650000]        <1> 	mov	ebx, u.ttyp
  2742                              <1> 	; 13/01/2014
  2743 0000518B F6C202              <1> 	test	dl, 2	; open for read sign
  2744 0000518E 7501                <1> 	jnz	short ottys_4
  2745 00005190 43                  <1> 	inc	ebx
  2746                              <1> ottys_4:
  2747                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2748 00005191 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2749                              <1> 	; 27/02/2022
  2750 00005193 08D2                <1> 	or	dl, dl	; sysstty system call check (DL=0)
  2751 00005195 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2752                              <1> sret:
  2753                              <1> 	;pop 	ax
  2754                              <1> 	; 04/02/2022
  2755 00005197 58                  <1> 	pop	eax
  2756                              <1> otty_retn:	; 12/02/2022
  2757                              <1> iclose_retn:	
  2758 00005198 C3                  <1> 	retn
  2759                              <1> 
  2760                              <1> 	;
  2761                              <1> 	; Original UNIX v1 'otty' routine:
  2762                              <1> 	;	
  2763                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2764                              <1>         ;                 / reader status reg
  2765                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2766                              <1>         ;                 / punch status reg
  2767                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2768                              <1>         ;                          / console tty buffer
  2769                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2770                              <1>         ;            / console tty
  2771                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2772                              <1>         ;             / buffer header
  2773                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2774                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2775                              <1>         ;                 / tty
  2776                              <1>         ;br     sret / ?
  2777                              <1> ;sret:
  2778                              <1> 		; clr *$ps / set processor priority to zero
  2779                              <1> ;	pop	ax
  2780                              <1>         	; mov (sp)+,r1 / pop stack to r1
  2781                              <1> ;3:
  2782                              <1> ;	retn
  2783                              <1>         	; rts r0
  2784                              <1> 	
  2785                              <1> ;ocvt:	; < open tty >
  2786                              <1> 	; 13/01/2014
  2787                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2788                              <1> 	; 24/09/2013 consistency check -> ok
  2789                              <1> 	; 16/09/2013
  2790                              <1> 	; 03/09/2013
  2791                              <1> 	; 27/08/2013
  2792                              <1> 	; 16/08/2013
  2793                              <1> 	; 16/07/2013
  2794                              <1> 	; 27/05/2013
  2795                              <1> 	; 21/05/2013
  2796                              <1> 	;
  2797                              <1> 	; Retro UNIX 8086 v1 modification !
  2798                              <1> 	; 
  2799                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2800                              <1> 	;		(exactly different than this one)
  2801                              <1> 	;	was in 'u9.s' file.
  2802                              <1> 	;
  2803                              <1> 	; 16/07/2013
  2804                              <1> 	; Retro UNIX 8086 v1 modification:
  2805                              <1> 	;  If a tty is open for read or write by
  2806                              <1> 	;     a process (u.uno), only same process can open
  2807                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2808                              <1> 	;
  2809                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2810                              <1> 
  2811                              <1> 	; 16/09/2013
  2812                              <1> 	; sub 	al, 10
  2813                              <1> 	
  2814                              <1> 	; 06/12/2013
  2815                              <1> 	;cmp	al, 7
  2816                              <1>         ;jna     short ottyp
  2817                              <1> 	; 13/01/2014
  2818                              <1> 	;jmp	short ottyp
  2819                              <1> 
  2820                              <1> 
  2821                              <1> ;oppt: / open paper tape for reading or writing
  2822                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2823                              <1> ;        tstb   pptiflg / is file already open
  2824                              <1> ;        bne    2f / yes, branch
  2825                              <1> ;1:
  2826                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2827                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2828                              <1> ;               br .+4 / for paper tape input and place in free list
  2829                              <1> ;        br     1b
  2830                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2831                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2832                              <1> ;        br     sret
  2833                              <1> ;2:
  2834                              <1> ;        jmp    error / file already open
  2835                              <1> 
  2836                              <1> iclose: 
  2837                              <1> 	; 04/02/2022
  2838                              <1> 	; 19/05/2015
  2839                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2840                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2841                              <1> 	;
  2842                              <1> 	; close file whose i-number is in r1
  2843                              <1> 	; 
  2844                              <1> 	; INPUTS ->
  2845                              <1> 	;    r1 - inode number
  2846                              <1> 	; OUTPUTS ->
  2847                              <1> 	;    file's inode in core	
  2848                              <1> 	;    r1 - inode number (positive)
  2849                              <1> 	;
  2850                              <1> 	; ((AX = R1))
  2851                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2852                              <1> 	;        
  2853                              <1> ;/ close file whose i-number is in r1
  2854 00005199 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2855 0000519B F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2856                              <1> 		; tst r1 / test i-number
  2857                              <1>         ;jnz	short iclose_2
  2858                              <1> 		; blt 2f / if neg., branch
  2859 0000519E 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2860                              <1> 	; 16/07/2013 
  2861 000051A0 66F7D8              <1> 	neg	ax ; make it positive
  2862                              <1> 	; 12/01/2014
  2863 000051A3 FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2864                              <1> iclose_0:
  2865 000051A5 6683F828            <1> 	cmp	ax, 40
  2866                              <1> 		; cmp r1,$40. / is it a special file
  2867 000051A9 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2868                              <1> 		; bgt 3b / no, return
  2869                              <1> 	; 12/01/2014
  2870                              <1> 	; DL=2 -> special file was opened for reading
  2871                              <1> 	; DL=1 -> special file was opened for writing
  2872                              <1> 	; 04/02/2022
  2873 000051AB 50                  <1> 	push	eax
  2874                              <1> 	;push	ax
  2875                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2876 000051AC 0FB6D8              <1> 	movzx	ebx, al
  2877                              <1> 	; 04/02/2022
  2878 000051AF C0E302              <1> 	shl	bl, 2
  2879                              <1> 	;shl	bx, 2
  2880                              <1> 		; asl r1
  2881 000051B2 81C3[B6510000]      <1> 	add	ebx, iclose_1 - 4
  2882 000051B8 FF23                <1> 	jmp	dword [ebx]
  2883                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2884                              <1> iclose_1 :
  2885 000051BA [06520000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2886 000051BE [61520000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2887 000051C2 [61520000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2888 000051C6 [61520000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2889 000051CA [61520000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2890 000051CE [61520000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2891 000051D2 [61520000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2892 000051D6 [61520000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2893 000051DA [61520000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2894                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2895                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2896 000051DE [15520000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2897 000051E2 [15520000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2898 000051E6 [15520000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2899 000051EA [15520000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2900 000051EE [15520000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2901 000051F2 [15520000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2902 000051F6 [15520000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2903 000051FA [15520000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2904 000051FE [15520000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2905 00005202 [15520000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2906                              <1> 
  2907                              <1> 	; 1:
  2908                              <1> 	;        ctty   / tty
  2909                              <1> 	;        cppt   / ppt
  2910                              <1> 	;        sret   / mem
  2911                              <1> 	;        sret   / rf0
  2912                              <1> 	;        sret   / rk0
  2913                              <1> 	;        sret   / tap0
  2914                              <1> 	;        sret   / tap1
  2915                              <1> 	;        sret   / tap2
  2916                              <1> 	;        sret   / tap3
  2917                              <1> 	;        sret   / tap4
  2918                              <1> 	;        sret   / tap5
  2919                              <1> 	;        sret   / tap6
  2920                              <1> 	;        sret   / tap7
  2921                              <1> 	;        ccvt   / tty0
  2922                              <1> 	;        ccvt   / tty1
  2923                              <1> 	;        ccvt   / tty2
  2924                              <1> 	;        ccvt   / tty3
  2925                              <1> 	;        ccvt   / tty4
  2926                              <1> 	;        ccvt   / tty5
  2927                              <1> 	;        ccvt   / tty6
  2928                              <1> 	;        ccvt   / tty7
  2929                              <1> 	;        error / crd
  2930                              <1> 
  2931                              <1> ;iclose_2: ; 2: / negative i-number
  2932                              <1> 	;neg	ax
  2933                              <1> 		;neg r1 / make it positive
  2934                              <1> 	;cmp	ax, 40
  2935                              <1> 		;cmp r1,$40. / is it a special file?
  2936                              <1>         ;ja	short @b
  2937                              <1> 		;bgt    3b / no. return
  2938                              <1> 	;push	ax
  2939                              <1> 		;mov r1,-(sp)
  2940                              <1> 	;movzx	ebx, al
  2941                              <1> 	;shl	bx, 1
  2942                              <1> 		;asl r1 / yes. compute jump address and transfer
  2943                              <1> 	;add	ebx, iclose_3 - 2
  2944                              <1> 	;jmp	dword [ebx]
  2945                              <1> 		;jmp *1f-2(r1) / figure out 
  2946                              <1> ;iclose_3:
  2947                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2948                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2949                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2950                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2951                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2952                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2953                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2954                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2955                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2956                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2957                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2958                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2959                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2960                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2961                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2962                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2963                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2964                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2965                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2966                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2967                              <1> 	
  2968                              <1> 	;1:
  2969                              <1> 	;      	ctty   / tty
  2970                              <1> 	;       leadr  / ppt
  2971                              <1> 	;       sret   / mem
  2972                              <1> 	;       sret   / rf0
  2973                              <1> 	;       sret   / rk0
  2974                              <1> 	;       sret   / tap0
  2975                              <1> 	;       sret   / tap1
  2976                              <1> 	;       sret   / tap2
  2977                              <1> 	;       sret   / tap3
  2978                              <1> 	;       sret   / tap4
  2979                              <1> 	;       sret   / tap5
  2980                              <1> 	;       sret   / tap6
  2981                              <1> 	;       sret   / tap7
  2982                              <1> 	;       ccvt   / tty0
  2983                              <1> 	;       ccvt   / tty1
  2984                              <1> 	;       ccvt   / tty2
  2985                              <1> 	;       ccvt   / tty3
  2986                              <1> 	;       ccvt   / tty4
  2987                              <1> 	;       ccvt   / tty5
  2988                              <1> 	;       ccvt   / tty6
  2989                              <1> 	;       ccvt   / tty7
  2990                              <1> 	;/       ejec / lpr
  2991                              <1> 
  2992                              <1> ctty: ; / close console tty
  2993                              <1> 	; 25/02/2022
  2994                              <1> 	; 12/02/2022
  2995                              <1> 	; 05/02/2022
  2996                              <1> 	; 04/02/2022
  2997                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2998                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2999                              <1> 	;
  3000                              <1> 	; Retro UNIX 8086 v1 modification !
  3001                              <1> 	; (DL = 2 -> it is open for reading)
  3002                              <1> 	; (DL = 1 -> it is open for writing)
  3003                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3004                              <1> 	;
  3005                              <1> 	; 06/12/2013
  3006 00005206 0FB61D[49650000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3007 0000520D 8A83[53620000]      <1>         mov     al, [ebx+p.ttyc-1]
  3008                              <1> 	; 13/01/2014
  3009                              <1> 	;jmp	short cttyp
  3010                              <1> 	; 05/02/2022
  3011 00005213 EB04                <1> 	jmp	short ctty_0
  3012                              <1> ccvt:
  3013 00005215 2C0A                <1> 	sub 	al, 10
  3014                              <1> cttyp:	; (call from sysstty)
  3015                              <1> 	; 08/01/2022
  3016 00005217 31DB                <1> 	xor	ebx, ebx
  3017                              <1> ctty_0:	
  3018                              <1> 	; 18/05/2015 (32 bit modifications)
  3019                              <1> 	; 16/08/2013 - 26/01/2014
  3020                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3021                              <1> 	; 04/02/2022
  3022 00005219 88C3                <1> 	mov	bl, al
  3023 0000521B D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3024                              <1> 	; 26/01/2014
  3025 0000521D 81C3[84610000]      <1> 	add 	ebx, ttyl
  3026 00005223 88C6                <1> 	mov 	dh, al ; tty number
  3027 00005225 668B03              <1> 	mov 	ax, [ebx]
  3028                              <1> 		   ; AL = lock value (0 or process number)
  3029                              <1> 		   ; AH = open count 
  3030 00005228 20E4                <1> 	and 	ah, ah
  3031 0000522A 7514                <1> 	jnz	short ctty_ret
  3032                              <1>   	; 12/02/2022
  3033 0000522C 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3034 0000522F 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3035                              <1> 	; iclose (dl=1 or dl=2)
  3036 00005231 C705[4F650000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3036 00005239 0000                <1>
  3037                              <1> 			; device not open ! error
  3038                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3039 0000523B E9A1DEFFFF          <1> 	jmp	error
  3040                              <1> 	; 26/01/2014
  3041                              <1> ctty_ret:
  3042 00005240 FECC                <1> 	dec 	ah ; decrease open count
  3043 00005242 7502                <1> 	jnz	short ctty_1
  3044 00005244 30C0                <1> 	xor	al, al ; unlock/free tty
  3045                              <1> ctty_1:
  3046 00005246 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3047                              <1> 	;
  3048 00005249 BB[30650000]        <1> 	mov	ebx, u.ttyp
  3049                              <1> 	;test	dl, 1 ; open for write sign
  3050                              <1> 	;jz	short ctty_2
  3051                              <1> 	; 25/02/2022
  3052 0000524E F6C202              <1> 	test	dl, 2 ; open for read sign
  3053 00005251 7501                <1> 	jnz	short ctty_2
  3054 00005253 43                  <1> 	inc	ebx
  3055                              <1> ctty_2:
  3056 00005254 FEC6                <1> 	inc	dh ; tty number + 1
  3057 00005256 3A33                <1> 	cmp	dh, [ebx]
  3058                              <1> 	;jne	short cret
  3059 00005258 7503                <1> 	jne	short ctty_3 ; 12/02/2022
  3060                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3061 0000525A C60300              <1> 	mov	byte [ebx], 0
  3062                              <1> ctty_3:
  3063                              <1> 	; 12/02/2022
  3064 0000525D 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3065 0000525F 7401                <1> 	jz	short ctty_4
  3066                              <1> cret:
  3067                              <1> 	;pop	ax
  3068                              <1> 	; 05/02/2022
  3069 00005261 58                  <1> 	pop	eax
  3070                              <1> ctty_stc_retn:	; 12/02/2022
  3071                              <1> ctty_4:
  3072 00005262 C3                  <1> 	retn
  3073                              <1> 
  3074                              <1> ;ctty_err: ; 13/01/2014
  3075                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3076                              <1> ;	jnz	error
  3077                              <1> ;	stc
  3078                              <1> ;	retn
  3079                              <1> 
  3080                              <1> 	; Original UNIX v1 'ctty' routine:
  3081                              <1> 	;	
  3082                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3083                              <1> 	;		;/ point r5 to the console tty buffer
  3084                              <1>         ;decb   (r5) / dec number of processes using console tty
  3085                              <1>         ;br     sret / return via sret
  3086                              <1> 
  3087                              <1> ;ccvt:	; < close tty >
  3088                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3089                              <1> 	;
  3090                              <1> 	; Retro UNIX 8086 v1 modification !
  3091                              <1> 	; 
  3092                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3093                              <1> 	;		(exactly different than this one)
  3094                              <1> 	;	was in 'u9.s' file.
  3095                              <1> 	;
  3096                              <1> 	; DL = 2 -> it is open for reading
  3097                              <1> 	; DL = 1 -> it is open for writing
  3098                              <1> 	;
  3099                              <1> 	; 17/09/2013
  3100                              <1> 	;sub 	al, 10
  3101                              <1> 	;cmp	al, 7
  3102                              <1> 	;jna	short cttyp
  3103                              <1> 	; 13/01/2014
  3104                              <1> 	;jmp	short cttyp
  3105                              <1> 
  3106                              <1> ;cppt: / close paper tape
  3107                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3108                              <1> ;1:
  3109                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3110                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3111                              <1> ;                          / and assign to free list
  3112                              <1> ;               br sret
  3113                              <1> ;        br     1b
  3114                              <1> 
  3115                              <1> ;ejec:	
  3116                              <1> ;	jmp	error
  3117                              <1> ;/ejec:
  3118                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3119                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3120                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3121                              <1> ;/       br     sret / return to caller via 'sret'
  3122                              <1> 
  3123                              <1> ejec:
  3124                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kewrnel v0.2.0.20)
  3125                              <1> 	;	     - Printer Initialization
  3126                              <1> lpt_init:	
  3127                              <1> 	; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985
  3128                              <1> 	;
  3129                              <1> 	; Default printer port: 378h ; LPT1
  3130                              <1> 	
  3131 00005263 B401                <1>  	mov	ah, 1  ; INITIALIZE THE PRINTER PORT
  3132                              <1> 	;call	int17h
  3133 00005265 E8BDFAFFFF          <1> 	call	PRNOP
  3134 0000526A 7414                <1> 	jz	short lpt_init_ok
  3135                              <1> 	
  3136                              <1> 	; replace error code with 'device not ready' error
  3137                              <1> 	; (this may be better for 'sysopen')
  3138 0000526C B80F000000          <1> 	mov	eax, ERR_PRN_NOT_RDY
  3139 00005271 A3[4F650000]        <1> 	mov	[u.error], eax
  3140                              <1> 	;jmp	sysret ; (may be) ? ([u.r0] = file descriptor)
  3141 00005276 A3[00650000]        <1> 	mov	[u.r0], eax
  3142 0000527B E961DEFFFF          <1> 	jmp	error ; (better)	
  3143                              <1> 	
  3144                              <1> lpt_init_ok:
  3145                              <1> 	;jmp	short cret
  3146 00005280 58                  <1> 	pop	eax    ; inode number
  3147 00005281 C3                  <1> 	retn
  3148                              <1> 	
  2059                                  %include 'u8.s'        ; 11/06/2015
  2060                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS8.INC
  2061                              <1> ; Last Modification: 19/07/2022
  2062                              <1> ; ----------------------------------------------------------------------------
  2063                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2064                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2065                              <1> ;
  2066                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2067                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2068                              <1> ; <Bell Laboratories (17/3/1972)>
  2069                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2070                              <1> ;
  2071                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2072                              <1> ;
  2073                              <1> ; ****************************************************************************
  2074                              <1> ; 24/10/2015
  2075                              <1> 
  2076                              <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2077                              <1> ;---------------------------------------------------------------------
  2078                              <1> ; Buffer Header: -8 bytes-
  2079                              <1> ; word 1 - byte 0 - device (disk index) number (0 to 5)
  2080                              <1> ;	   byte 1 - status bits
  2081                              <1> ;	 	bit 0 - valid buffer bit (1 = valid, 0 = invalid, new)
  2082                              <1> ;		bit 1 - write bit (also modified bit)
  2083                              <1> ;		bit 2 - read bit	
  2084                              <1> ;		bit 3 to bit 7 are not used
  2085                              <1> ; word 2 - byte & byte 3 not used
  2086                              <1> ; word 3 & word 4 - byte 3, byte 5, byte 6, byte 7:
  2087                              <1> ;		physical block/sector address (32 bit LBA)
  2088                              <1> ;---------------------------------------------------------------------
  2089                              <1> 
  2090                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2091                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2092                              <1> ;; Word 1, byte 0 = device id
  2093                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2094                              <1> ;;          bit 9 = write bit
  2095                              <1> ;;	    bit 10 = read bit	  
  2096                              <1> ;;	    bit 12 = waiting to write bit	
  2097                              <1> ;;	    bit 13 = waiting to read bit
  2098                              <1> ;;	    bit 15 = inhibit bit
  2099                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2100                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2101                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2102                              <1> ;;
  2103                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2104                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2105                              <1> ;;
  2106                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2107                              <1> ;; Word 1, Byte 0 = device id
  2108                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2109                              <1> ;;          bit 9 = write bit
  2110                              <1> ;;	    bit 10 = read bit	  
  2111                              <1> ;;	    bit 12 = waiting to write bit	
  2112                              <1> ;;	    bit 13 = waiting to read bit
  2113                              <1> ;;	    bit 15 = inhibit bit
  2114                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2115                              <1> ;;
  2116                              <1> ;; Original UNIX v1 ->
  2117                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2118                              <1> ;; Original UNIX v1 -> 
  2119                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2120                              <1> ;;
  2121                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2122                              <1> ;;
  2123                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2124                              <1> ;;          0 = fd0
  2125                              <1> ;;	    1 = fd1
  2126                              <1> ;;	    2 = hd0
  2127                              <1> ;;	    3 = hd1
  2128                              <1> ;;	    4 = hd2
  2129                              <1> ;;	    5 = hd3
  2130                              <1> 
  2131                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2132                              <1> 
  2133                              <1> 	; 04/02/2022
  2134                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2135                              <1> 	; 26/04/2013
  2136                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2137                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2138                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2139                              <1> 
  2140                              <1> 	; 04/02/2022
  2141                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2142                              <1> 	; 26/04/2013
  2143                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2144                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2145                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2146                              <1> 
  2147                              <1> bread: 
  2148                              <1> 	; 19/07/2022
  2149                              <1> 	; 14/07/2022
  2150                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2151                              <1> 	; 12/02/2022
  2152                              <1> 	; 04/02/2022
  2153                              <1> 	; 14/07/2015
  2154                              <1> 	; 10/07/2015
  2155                              <1> 	; 09/06/2015
  2156                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2157                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2158                              <1> 	;	
  2159                              <1> 	; / read a block from a block structured device
  2160                              <1> 	;
  2161                              <1> 	; INPUTS ->
  2162                              <1> 	;    [u.fofp] points to the block number
  2163                              <1> 	;    ECX = maximum block number allowed on device
  2164                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2165                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2166                              <1> 	;    [u.count]	number of bytes to read in
  2167                              <1> 	; OUTPUTS ->
  2168                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2169                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2170                              <1> 	;
  2171                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX, ESI, EDI))
  2172                              <1> 	;
  2173                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2174                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2175                              <1> 	;	is increased by 1. For example: If user/program request 
  2176                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2177                              <1> 	;  	the next block number just as 512 byte reading is done.
  2178                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2179                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2180                              <1> 	;       enough to keep byte position/offset of the disk), this
  2181                              <1> 	;	defect will not be corrected, user/program must request
  2182                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2183                              <1> 	;       for achieving correct result. In future version(s), 
  2184                              <1> 	;	this defect will be corrected by using different 
  2185                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2186                              <1> 
  2187                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2188                              <1> 			       ; / (only works on tape)
  2189                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2190                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2191                              <1> ;1:
  2192                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2193                              <1> 			    ; / maximum block # allowed on device
  2194                              <1> 		; jnb short @f
  2195                              <1> 		; bhis	1f / yes, 1f (error)
  2196                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2197                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2198                              <1> 		; mov (sp)+,r1 / return block # to r1
  2199                              <1> 		; inc r1 / bump block # to next consecutive block
  2200                              <1> 		; dec (sp) / "2-1-cold" on stack
  2201                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2202                              <1> ;1:
  2203                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2204                              <1> 	;push	ecx ; **
  2205                              <1> 	;26/04/2013
  2206                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2207 00005282 2C03                <1> 	sub	al, 3
  2208                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2209 00005284 A2[62650000]        <1> 	mov	[u.brwdev], al
  2210                              <1> 	; 09/06/2015
  2211                              <1> 	;movzx	ebx, al
  2212                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2213                              <1> 	; 04/02/2022 (BugFix)
  2214 00005289 C0E002              <1> 	shl	al, 2 ; * 4
  2215 0000528C 8B88[625C0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2216                              <1> bread_0:
  2217 00005292 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2218                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2219                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2220 00005293 8B1D[10650000]      <1> 	mov	ebx, [u.fofp]
  2221 00005299 8B03                <1> 	mov	eax, [ebx]
  2222 0000529B C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2223                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2224                              <1> 			       ; / block #
  2225 0000529E 39C8                <1> 	cmp	eax, ecx
  2226                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2227                              <1>        	                     ; / block number allowed
  2228                              <1> 	;jnb	error 	     ; 18/04/2013
  2229                              <1> 		; bhis error10 / yes, error
  2230                              <1> 	; 12/02/2022
  2231                              <1> 	;jb	short bread_1
  2232                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2233                              <1> 	;jmp	error
  2234 000052A0 7346                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2235                              <1> bread_1:
  2236                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2237                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2238                              <1> 	; EAX = Block number (zero based)
  2239                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2240                              <1> preread: ;; call preread
  2241 000052A2 BF[62650000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2242 000052A7 E8DC010000          <1> 	call	bufaloc_0 ; 26/04/2013
  2243                              <1> 	;; jc 	error
  2244                              <1> 	; EBX = Buffer (Header) Address -Physical-
  2245                              <1>         ; EAX = Block/Sector number (r1)
  2246                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2247                              <1> 	; 14/03/2013
  2248 000052AC 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2249                              <1>        		; br 1f / branch if block already in a I/O buffer
  2250 000052AE 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2251                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2252 000052B3 E8A8010000          <1> 	call	poke
  2253                              <1>         	; jsr r0,poke / perform the read
  2254                              <1> 	;;jc	error ;2 0/07/2013
  2255                              <1> ; 1:
  2256                              <1>  		; clr *$ps / ps = 0
  2257                              <1>         	; rts r0
  2258                              <1> 	; 12/02/2022
  2259 000052B8 7305                <1> 	jnc	short bread_2
  2260 000052BA E919010000          <1> 	jmp	dskrd_err
  2261                              <1> 
  2262                              <1> ;; return from preread
  2263                              <1> bread_2:
  2264                              <1> 	; 14/07/2022
  2265                              <1> 	;or	word [ebx], 4000h 
  2266                              <1> 	;	; bis $40000,(r5) 
  2267                              <1> 	;		; / set bit 14 of the 1st word of the I/O buffer
  2268                              <1> bread_3: ; 1:
  2269                              <1> 	; 14/07/2022
  2270                              <1> 	;test	word [ebx], 2400h
  2271                              <1> 	;	; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2272                              <1> 	;jz	short bread_4
  2273                              <1> 	;	; beq 1f / no
  2274                              <1> 	;	; cmp cdev,$1 / disk or drum?
  2275                              <1> 	;	; ble 2f / yes
  2276                              <1> 	;	; tstb uquant / is the time quantum = 0?
  2277                              <1> 	;	; bne 2f / no, 2f
  2278                              <1> 	;	; mov r5,-(sp) / yes, save r5 (buffer address)
  2279                              <1> 	;	; jsr r0,sleep; 31. 
  2280                              <1> 	;		; / put process to sleep in channel 31 (tape)
  2281                              <1> 	;	; mov (sp)+,r5 / restore r5
  2282                              <1> 	;	; br 1b / go back
  2283                              <1> ; 2: / drum or disk
  2284                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2285                              <1> 	;call	idle
  2286                              <1> 	;	; jsr r0,idle; s.wait+2 / wait
  2287                              <1> 	;jmp	short bread_3
  2288                              <1>        	;	; br 1b
  2289                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2290                              <1> 	;and	word [ebx], 0BFFFh ; 1011111111111111b
  2291                              <1> 	;	; bic $40000,(r5) / clear bit 14
  2292                              <1>        	;	; jsr r0,tstdeve / test device for error (tape)
  2293                              <1> 	; 14/07/2022
  2294 000052BF 83C308              <1> 	add	ebx, 8
  2295                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2296                              <1> 	; 09/06/2015
  2297 000052C2 66833D[5F650000]00  <1> 	cmp	word [u.pcount], 0
  2298 000052CA 7705                <1> 	ja	short bread_5
  2299 000052CC E892F8FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2300                              <1> bread_5:
  2301                              <1> 	; EBX = system (I/O) buffer address
  2302 000052D1 E87C000000          <1> 	call	dioreg
  2303                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2304                              <1> 
  2305                              <1> 	; 19/07/2022
  2306                              <1> 	; EDI = user data offset (previous value of [u.pbase])
  2307                              <1> 	; ESI = pointer to file offset 
  2308                              <1> 	; EAX = system (I/O) buffer offset (>= EBX)
  2309                              <1> 	; ECX = byte count
  2310                              <1> 	; EBX = system buffer (data) address
  2311                              <1> 
  2312                              <1> 	; 19/07/2022
  2313 000052D6 010E                <1> 	add	[esi], ecx ; new file (disk) offset
  2314 000052D8 89C6                <1> 	mov	esi, eax 
  2315                              <1> 
  2316                              <1> 	; esi = start address of the transfer (in the buffer)
  2317                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2318                              <1> 	; ecx = transfer count (in bytes)
  2319                              <1> 	;
  2320                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2321                              <1> ;   / of users data
  2322 000052DA F3A4                <1> 	rep	movsb
  2323                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2324                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2325                              <1>        		; bne 1b
  2326 000052DC 59                  <1> 	pop	ecx ; **
  2327 000052DD 833D[24650000]00    <1> 	cmp	dword [u.count], 0
  2328                              <1> 		; tst u.count / done
  2329 000052E4 77AC                <1> 	ja	short bread_0 ; 09/06/2015
  2330                              <1>        		; beq 1f / yes, return
  2331                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2332                              <1>        		; br bread / read some more
  2333                              <1> ; 1:
  2334 000052E6 58                  <1> 	pop	eax ; ****
  2335                              <1>        		; mov (sp)+,r0
  2336 000052E7 C3                  <1>         retn		; 09/06/2015
  2337                              <1> 	;jmp	ret_ 
  2338                              <1> 		;jmp ret / jump to routine that called readi
  2339                              <1> 
  2340                              <1> 	; 08/02/2022
  2341                              <1> brw_oov_err:
  2342 000052E8 C705[4F650000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2342 000052F0 0000                <1>
  2343 000052F2 E9EADDFFFF          <1> 	jmp	error
  2344                              <1> 
  2345                              <1> 	; 12/02/2022
  2346                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2347                              <1> 	; 26/04/2013
  2348                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2349                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2350                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2351                              <1> 
  2352                              <1> 	; 12/02/2022				
  2353                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2354                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2355                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2356                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2357                              <1> 
  2358                              <1> bwrite: 
  2359                              <1> 	; 19/07/2022
  2360                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  2361                              <1> 	; 14/07/2022
  2362                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2363                              <1> 	; 12/02/2022
  2364                              <1> 	; 04/02/2022
  2365                              <1> 	; 14/07/2015
  2366                              <1> 	; 10/07/2015
  2367                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2368                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2369                              <1> 	;	
  2370                              <1> 	;; / write on block structured device
  2371                              <1> 	;
  2372                              <1> 	; INPUTS ->
  2373                              <1> 	;    [u.fofp] points to the block number
  2374                              <1> 	;    ECX = maximum block number allowed on device
  2375                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2376                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2377                              <1> 	;    [u.count]	number of bytes to user desires to write
  2378                              <1> 	; OUTPUTS ->
  2379                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2380                              <1> 	;
  2381                              <1> 	; ((Modified registers: EDX, ECX, EBX, ESI, EDI))
  2382                              <1> 	;
  2383                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2384                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2385                              <1> 	;	is increased by 1. For example: If user/program request 
  2386                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2387                              <1> 	;  	the next block number just as 512 byte writing is done.
  2388                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2389                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2390                              <1> 	;       enough to keep byte position/offset of the disk), this
  2391                              <1> 	;	defect will not be corrected, user/program must request
  2392                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2393                              <1> 	;       for achieving correct result. In future version(s), 
  2394                              <1> 	;	this defect will be corrected by using different 
  2395                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2396                              <1> 
  2397                              <1>        		; jsr r0,tstdeve / test the device for an error
  2398                              <1> 	;push	ecx ; **
  2399                              <1> 	;26/04/2013
  2400                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2401 000052F7 2C03                <1> 	sub	al, 3
  2402                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2403 000052F9 A2[62650000]        <1> 	mov	[u.brwdev], al
  2404                              <1> 	; 09/06/2015
  2405                              <1> 	;movzx	ebx, al
  2406                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2407                              <1> 	; 04/02/2022 (BugFix)
  2408 000052FE C0E002              <1> 	shl	al, 2 ; * 4
  2409 00005301 8B88[625C0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2410                              <1> bwrite_0:
  2411 00005307 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2412                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2413                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2414 00005308 8B1D[10650000]      <1> 	mov	ebx, [u.fofp]
  2415 0000530E 8B03                <1> 	mov	eax, [ebx]       
  2416 00005310 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2417                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2418 00005313 39C8                <1> 	cmp	eax, ecx
  2419                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2420                              <1>        	                     ; / block number allowed
  2421                              <1> 	;jnb	error	     ; 18/04/2013
  2422                              <1> 		; bhis error10 / yes, error
  2423                              <1>      	; 12/02/2022
  2424                              <1> 	;jb	short bwrite_1
  2425                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2426                              <1> 	;jmp	error
  2427 00005315 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2428                              <1> bwrite_1:
  2429                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2430                              <1> 		; inc *u.fofp / no, increment block number
  2431                              <1> 	; 09/06/2015 - 10/07/2015
  2432 00005317 66833D[5F650000]00  <1> 	cmp	word [u.pcount], 0
  2433 0000531F 7705                <1> 	ja	short bwrite_2
  2434 00005321 E839F8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2435                              <1> bwrite_2:
  2436 00005326 BF[62650000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2437 0000532B E8C9000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2438                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2439                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2440 00005330 E81D000000          <1>         call	dioreg
  2441                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2442                              <1> 
  2443                              <1> 	; 19/07/2022
  2444                              <1> 	; EDI = user data offset (previous value of [u.pbase])
  2445                              <1> 	; ESI = pointer to file offset 
  2446                              <1> 	; EAX = system (I/O) buffer offset (>= EBX)
  2447                              <1> 	; ECX = byte count
  2448                              <1> 	; EBX = system buffer (data) address
  2449                              <1> 
  2450                              <1> 	; 19/07/2022 - Erdogan Tan
  2451                              <1> 	; ((Against a possible disk write failure/error, 
  2452                              <1> 	;   file offset must not be updated/increased before 'dskwr'
  2453                              <1> 	;   but it was updated in 'dioreg'. I have modified 'dioreg'
  2454                              <1> 	;   and 'bwrite' procedures for that.))
  2455                              <1> 
  2456                              <1> 	; 19/07/2022
  2457 00005335 56                  <1> 	push	esi ; (!)  ; save file offset (pointer)
  2458 00005336 51                  <1> 	push	ecx ; (!!) ; save byte count
  2459                              <1> 	;mov	esi, eax
  2460                              <1> 	
  2461                              <1> 	; esi = destination address (in the buffer)
  2462                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2463                              <1> 	; ecx = transfer count (in bytes)
  2464                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2465                              <1> 	;xchg 	esi, edi ; 14/07/2015
  2466                              <1> 
  2467                              <1> 	; 19/07/2022
  2468 00005337 89FE                <1> 	mov	esi, edi
  2469 00005339 89C7                <1> 	mov	edi, eax
  2470                              <1> 	
  2471 0000533B F3A4                <1> 	rep	movsb
  2472                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2473                              <1>        		; dec r3 / area to the I/O buffer
  2474                              <1>        		; bne 1b
  2475                              <1> 
  2476 0000533D E8F0000000          <1> 	call	dskwr
  2477                              <1> 		; jsr r0,dskwr / write it out on the device
  2478                              <1> 
  2479                              <1> 	; 19/07/2022
  2480                              <1> 	; (there is not a disk write error, we can increase file offset)
  2481 00005342 58                  <1> 	pop	eax ; (!!) ; byte count
  2482 00005343 5F                  <1> 	pop	edi ; (!)  ; file offset (pointer)
  2483                              <1> 	;
  2484 00005344 0107                <1> 	add	[edi], eax ; new file offset (old offset + byte count)
  2485                              <1> 
  2486 00005346 59                  <1> 	pop	ecx ; **
  2487                              <1> 
  2488 00005347 833D[24650000]00    <1>         cmp     dword [u.count], 0
  2489                              <1> 		; tst u.count / done
  2490 0000534E 77B7                <1> 	ja	short bwrite_0 ; 09/06/2015
  2491                              <1> 		; beq 1f / yes, 1f
  2492                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2493                              <1>        		; br bwrite / go back and write next block
  2494                              <1> ; 1:
  2495 00005350 58                  <1> 	pop	eax ; ****
  2496                              <1>        		; mov (sp)+,r0
  2497 00005351 C3                  <1> 	retn		; 09/06/2015
  2498                              <1>         ;jmp	ret_ 
  2499                              <1> 		; jmp ret / return to routine that called writei
  2500                              <1> ;error10:
  2501                              <1> ;       jmp     error  ; / see 'error' routine
  2502                              <1> 
  2503                              <1> dioreg:
  2504                              <1> 	; 19/07/2022
  2505                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  2506                              <1> 	; 04/02/2022
  2507                              <1> 	; 14/07/2015
  2508                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2509                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2510                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2511                              <1> 	;	
  2512                              <1> 	; bookkeeping on block transfers of data
  2513                              <1> 	;
  2514                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2515                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2516                              <1> 	; 10/07/2015
  2517                              <1> 	; * returns byte offset from beginning of current sector buffer
  2518                              <1> 	; (beginning of data) in ESI
  2519                              <1> 
  2520                              <1> 
  2521                              <1> 	; 19/07/2022
  2522                              <1> 	; OUTPUTS:
  2523                              <1> 	;   EDI = user data offset (previous value of [u.pbase])
  2524                              <1> 	;   ESI = pointer to file offset 
  2525                              <1> 	;   EAX = system (I/O) buffer offset
  2526                              <1> 	;   ECX = byte count
  2527                              <1> 	;   EBX = system buffer (data) address	
  2528                              <1> 
  2529 00005352 8B0D[24650000]      <1> 	mov	ecx, [u.count]
  2530                              <1> 		; mov u.count,r3 / move char count to r3
  2531                              <1>         ; 04/02/2022
  2532 00005358 31D2                <1> 	xor	edx, edx
  2533 0000535A B602                <1> 	mov	dh, 2
  2534                              <1> 	; edx = 512
  2535 0000535C 39D1                <1> 	cmp	ecx, edx ; 512
  2536                              <1> 	;cmp 	ecx, 512
  2537                              <1> 		; cmp r3,$512. / more than 512. char?
  2538 0000535E 7602                <1> 	jna	short dioreg_0
  2539                              <1> 		; blos 1f / no, branch
  2540 00005360 89D1                <1> 	mov	ecx, edx ; 512
  2541                              <1> 	;mov	ecx, 512
  2542                              <1> 		; mov $512.,r3 / yes, just take 512.
  2543                              <1> dioreg_0:
  2544                              <1> 	; 09/06/2015
  2545 00005362 663B0D[5F650000]    <1> 	cmp	cx, [u.pcount]
  2546 00005369 7607                <1> 	jna	short dioreg_1
  2547 0000536B 668B0D[5F650000]    <1> 	mov	cx, [u.pcount]
  2548                              <1> dioreg_1:
  2549                              <1> ; 1:
  2550 00005372 8B15[20650000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2551                              <1> 	        ; mov u.base,r2 / put users base in r2
  2552 00005378 010D[28650000]      <1> 	add	[u.nread], ecx
  2553                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2554 0000537E 290D[24650000]      <1> 	sub	[u.count], ecx
  2555                              <1> 		; sub r3,u.count / update count
  2556 00005384 010D[20650000]      <1> 	add	[u.base], ecx
  2557                              <1> 		; add r3,u.base / update base
  2558                              <1> 	; 10/07/2015
  2559                              <1> 	; Retro UNIX 386 v1 - modification !
  2560                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2561                              <1> 	; (It will point to next byte position instead of next block no.)
  2562 0000538A 8B35[10650000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2563 00005390 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2564                              <1> 	; 19/07/2022
  2565                              <1> 	;add	[esi], ecx ; ecx is added to set the next byte position
  2566 00005392 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2567                              <1> 	;mov	esi, ebx   ; beginning of data in sector/block buffer
  2568                              <1> 	;add	esi, eax   ; esi contains start address of the transfer
  2569                              <1> 	; 19/07/2022
  2570 00005397 01D8                <1> 	add	eax, ebx   ; eax contains start address of the transfer	
  2571                              <1> 	; 09/06/2015 - 10/07/2015
  2572 00005399 66290D[5F650000]    <1> 	sub	[u.pcount], cx
  2573 000053A0 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2574 000053A6 8B3D[5B650000]      <1> 	mov	edi, [u.pbase]
  2575 000053AC 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2576 000053B2 01D7                <1> 	add	edi, edx
  2577 000053B4 893D[5B650000]      <1> 	mov	[u.pbase], edi
  2578 000053BA 010D[5B650000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2579 000053C0 C3                  <1> 	retn
  2580                              <1> 		; rts r0 / return
  2581                              <1> 
  2582                              <1> dskrd:
  2583                              <1> 	; 14/07/2022
  2584                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2585                              <1> 	; 12/02/2022
  2586                              <1> 	; 18/08/2015
  2587                              <1> 	; 02/07/2015
  2588                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2589                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2590                              <1> 	;
  2591                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2592                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2593                              <1> 	; (number specified in r1) in the acquired buffer.
  2594                              <1> 	; If the device is busy at the time dskrd is called,	
  2595                              <1> 	; dskrd calls idle.
  2596                              <1> 	; 
  2597                              <1> 	; INPUTS ->
  2598                              <1> 	;    r1 - block number
  2599                              <1> 	;    cdev - current device number 
  2600                              <1> 	; OUTPUTS ->
  2601                              <1> 	;    r5 - points to first data word in I/O buffer
  2602                              <1> 	;
  2603                              <1> 	; ((AX = R1)) input/output
  2604                              <1> 	; ((BX = R5)) output 
  2605                              <1> 	;
  2606                              <1>         ; ((Modified registers: EDX, ECX, EBX, ESI, EDI))  
  2607                              <1> 	;
  2608 000053C1 E8B5000000          <1> 	call 	bufaloc
  2609                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2610                              <1> 			       ; / get a free I/O buffer
  2611                              <1> 	;;jc	error ; 20/07/2013
  2612 000053C6 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2613                              <1>        		; br 1f / branch if block already in a I/O buffer
  2614                              <1> 
  2615                              <1> 	; 14/07/2022
  2616                              <1> 	; (buffer header byte 1, bit 2 is disk read bit/flag)
  2617                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2618 000053C8 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2619                              <1>         ;	; bis $2000,(r5) / set bit 10 of word 1 of 
  2620                              <1> 	;	               ; / I/O queue entry for buffer
  2621 000053CD E88E000000          <1> 	call	poke
  2622                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2623                              <1> 			    ; /	bit 10=1 says read
  2624                              <1> 	; 09/06/2015
  2625                              <1> 	;jnc	short dskrd_1
  2626                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2627                              <1> 	;jmp	error
  2628                              <1> 	; 08/02/2022
  2629 000053D2 7204                <1> 	jc	short dskrd_3
  2630                              <1> dskrd_1: ; 1:
  2631                              <1>        	; 14/07/2022
  2632                              <1> 	;
  2633                              <1> 	;	;clr *$ps
  2634                              <1>        	;test	word [ebx], 2400h
  2635                              <1> 	;	; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2636                              <1> 	;			; / jump to idle
  2637                              <1>        	;jz	short dskrd_2
  2638                              <1> 	;	; beq 1f
  2639                              <1>         ;;;mov   ecx, [s.wait_]
  2640                              <1>        	;call	idle
  2641                              <1> 	;	; jsr r0,idle; s.wait+2
  2642                              <1> 	;jmp 	short dskrd_1
  2643                              <1>        	;	; br 1b
  2644                              <1> dskrd_2: ; 1:
  2645 000053D4 83C308              <1>         add	ebx, 8
  2646                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2647                              <1> 			  ; / just read in
  2648 000053D7 C3                  <1>        	retn
  2649                              <1> 		; rts r0
  2650                              <1> dskrd_err: 
  2651                              <1> 	; 08/02/2022
  2652                              <1> 	; (jump from 'bread' error)
  2653                              <1> dskrd_3:	
  2654                              <1> 	; 08/02/2022
  2655 000053D8 803D[62650000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2656 000053DF 7509                <1> 	jne	short dskrd_4 ; no
  2657                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2658 000053E1 C605[62650000]00    <1> 	mov	byte [u.brwdev], 0
  2659 000053E8 EB0A                <1> 	jmp	short dskrd_5
  2660                              <1> dskrd_4:
  2661 000053EA C705[4F650000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2661 000053F2 0000                <1>
  2662                              <1> dskrd_5:
  2663 000053F4 E9E8DCFFFF          <1> 	jmp	error
  2664                              <1> 
  2665                              <1> bwslot:
  2666                              <1> 	; 14/07/2022
  2667                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2668                              <1> 	; 04/02/2022
  2669                              <1> 	; 10/07/2015
  2670                              <1> 	;	If the block/sector is not placed in a buffer
  2671                              <1> 	;	before 'wslot', it must be read before
  2672                              <1> 	;	it is written! (Otherwise transfer counts less
  2673                              <1> 	;	than 512 bytes will be able to destroy existing 
  2674                              <1> 	;	data on disk.)
  2675                              <1> 	;
  2676                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2677                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2678                              <1> 	; Retro UNIX 8086 v1 modification !
  2679                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2680                              <1> 	; INPUT -> EDI - points to device id (in u.brwdev)	
  2681                              <1> 	;	-> EAX = block number
  2682                              <1> 	;
  2683 000053F9 E88A000000          <1> 	call	bufaloc_0
  2684 000053FE 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2685                              <1> 	; 04/02/2022
  2686                              <1> 	; ebx = buffer header address
  2687                              <1> bwslot_0:
  2688                              <1> 	; 10/07/2015
  2689 00005400 8B35[10650000]      <1> 	mov	esi, [u.fofp]
  2690 00005406 8B06                <1> 	mov	eax, [esi]
  2691 00005408 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2692 0000540D 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2693                              <1> 		       ; recent disk data must be placed in the buffer
  2694 0000540F 813D[24650000]0002- <1> 	cmp	dword [u.count], 512
  2694 00005417 0000                <1>
  2695 00005419 730F                <1> 	jnb	short wslot_0	
  2696                              <1> bwslot_1:
  2697 0000541B E8A8FFFFFF          <1> 	call	dskrd_0
  2698                              <1> 	; 04/02/2022
  2699                              <1> 	; ebx = buffer data address = buffer header address + 8
  2700 00005420 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2701 00005423 EB05                <1> 	jmp 	short wslot_0
  2702                              <1> 
  2703                              <1> wslot:
  2704                              <1> 	; 14/07/2022
  2705                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2706                              <1> 	;
  2707                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2708                              <1> 	; 		(32 bit modifications)
  2709                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2710                              <1> 	;
  2711                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2712                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2713                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2714                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2715                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2716                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2717                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2718                              <1> 	;
  2719                              <1> 	; INPUTS ->
  2720                              <1>  	;    r1 - block number
  2721                              <1> 	;    cdev - current (block/disk) device number
  2722                              <1>  	;
  2723                              <1> 	; OUTPUTS ->
  2724                              <1> 	;    bufp - bits 9 and 15 are set, 
  2725                              <1> 	;           the remainder of the word left unchanged
  2726                              <1> 	;    r5 - points to first data word in I/O buffer
  2727                              <1> 	;
  2728                              <1> 	; ((AX = R1)) input/output
  2729                              <1> 	; ((BX = R5)) output 
  2730                              <1> 	;
  2731                              <1>         ; ((Modified registers: EDX, ECX, EBX, ESI, EDI)) 
  2732                              <1> 
  2733 00005425 E851000000          <1> 	call	bufaloc
  2734                              <1> 	; 10/07/2015
  2735                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2736                              <1>         	; br 1f / word in buffer in r5
  2737                              <1> 	; EBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2738                              <1>         ; EAX = Block/Sector number (r1)
  2739                              <1> wslot_0: ;1:
  2740                              <1> 	; 14/07/2022
  2741                              <1> 	;
  2742                              <1>      	;test	word [ebx], 2400h
  2743                              <1> 	;	; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2744                              <1> 	;			; / of I/O queue entry
  2745                              <1> 	;jz	short wslot_1
  2746                              <1>         ;       ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2747                              <1> 	;	       ; / or not waiting to read)
  2748                              <1> 	;
  2749                              <1> 	;;mov	ecx, [s.wait_] ; 29/07/2013
  2750                              <1> 	;call	idle
  2751                              <1> 	;	; jsr r0,idle; / if buffer is reading or writing to read,
  2752                              <1>        	;                   ; / idle
  2753                              <1> 	;jmp	short wslot_0
  2754                              <1> 	;	; br 1b / till finished
  2755                              <1> wslot_1: ;1:
  2756                              <1> 	;or	word [ebx], 8200h
  2757                              <1>        	;	; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2758                              <1>         ;			; / (write, inhibit bits)
  2759                              <1> 	;	; clr *$ps / clear processor status
  2760                              <1> 
  2761                              <1> 	; 14/07/2022
  2762                              <1> 	; (set disk write bit/flag)
  2763                              <1> 	;or	word [ebx], 200h	
  2764 0000542A 43                  <1> 	inc	ebx
  2765 0000542B 800B02              <1> 	or	byte [ebx], 2
  2766 0000542E 83C307              <1> 	add	ebx, 7
  2767                              <1> 
  2768                              <1> 	;add	ebx, 8 ; 11/06/2015
  2769                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2770                              <1> 			  ; / for this block
  2771                              <1> dskwr_1:	; 08/02/2022
  2772 00005431 C3                  <1> 	retn
  2773                              <1> 		; rts r0
  2774                              <1> dskwr:
  2775                              <1> 	; 14/07/2022
  2776                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2777                              <1> 	; 12/02/2022
  2778                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2779                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2780                              <1> 	;
  2781                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2782                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2783                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2784                              <1> 	; previously has supplied all the information required in the
  2785                              <1> 	; I/O queue entry.
  2786                              <1> 	;
  2787                              <1> 	; (Modified registers: ECX, EDX, EBX, ESI, EDI)
  2788                              <1> 	;
  2789                              <1> 	;
  2790 00005432 8B1D[B8640000]      <1> 	mov	ebx, [bufp]
  2791                              <1> 	; 14/07/2022
  2792                              <1> 	;and	word [ebx], 7FFFh ; 0111111111111111b
  2793                              <1> 	;	; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2794                              <1>                                   ; / bottom of queue
  2795                              <1> 	; 14/07/2022
  2796                              <1> 	; (set disk write bit)
  2797                              <1> 	; ('wslot' already sets disk write bit/flag)
  2798                              <1> 	;mov	word [ebx], 200h
  2799                              <1> 
  2800 00005438 E823000000          <1> 	call	poke
  2801                              <1> 	; 09/06/2015
  2802 0000543D 73F2                <1> 	jnc	short dskwr_1
  2803                              <1> 	; 12/02/2022
  2804 0000543F 803D[62650000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2805 00005446 7509                <1> 	jne	short dskwr_0 ; no
  2806                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2807 00005448 C605[62650000]00    <1> 	mov	byte [u.brwdev], 0
  2808 0000544F EB0A                <1> 	jmp	short dskwr_2
  2809                              <1> dskwr_0:
  2810 00005451 C705[4F650000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2810 00005459 0000                <1>
  2811                              <1> dskwr_2:
  2812 0000545B E981DCFFFF          <1> 	jmp	error
  2813                              <1> ;dskwr_1:
  2814                              <1> ;	retn
  2815                              <1> 
  2816                              <1> ;ppoke:
  2817                              <1>        		; mov $340,*$ps
  2818                              <1>        		; jsr r0,poke
  2819                              <1>        		; clr *$ps
  2820                              <1> 		; rts r0
  2821                              <1> poke:
  2822                              <1> 	; 14/07/2022
  2823                              <1> 	;	! Major Modification !
  2824                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2825                              <1> 	;
  2826                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2827                              <1> 	; 24/10/2015
  2828                              <1> 	; 20/08/2015
  2829                              <1> 	; 18/08/2015
  2830                              <1> 	; 02/07/2015
  2831                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2832                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2833                              <1> 	;
  2834                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2835                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2836                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2837                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2838                              <1> 	;
  2839                              <1> 	; Basic I/O functions for all block structured devices
  2840                              <1> 	;
  2841                              <1>         ; (Modified registers: ECX, EDX, ESI, EDI)
  2842                              <1> 	;
  2843                              <1> 	; 20/07/2013 modifications
  2844                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2845                              <1> 	; INPUTS -> 
  2846                              <1> 	;        EBX = buffer header address
  2847                              <1> 	; OUTPUTS ->
  2848                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2849                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2850                              <1> 	;		(drive not ready or r/w error!)
  2851                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2852                              <1> 	;	 (dword [EBX+4] = 0FFFFFFFFh means RW/IO error)
  2853                              <1> 	;        (also it indicates invalid buffer data)
  2854                              <1> 	
  2855                              <1> 	; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2856                              <1> 	; Buffer header:
  2857                              <1> 	;	byte 0 - device/disk (index) number
  2858                              <1> 	;	byte 1 - status
  2859                              <1> 	;	    before 'poke'	
  2860                              <1> 	;		bit 0 - valid bit 
  2861                              <1> 	;		   (0 for new buffer)
  2862                              <1> 	;		   (1 for existing buffer)	
  2863                              <1> 	;		bit 1 - write (modified) bit, disk write flag
  2864                              <1> 	;		bit 2 - read bit, disk read flag
  2865                              <1> 	;	    after 'poke'
  2866                              <1> 	;		if disk r/w is successed
  2867                              <1> 	;		   bit 0 = 1
  2868                              <1> 	;		   bit 1 = 0
  2869                              <1> 	;		   bit 2 = 0
  2870                              <1> 	;		if disk r/w is failed
  2871                              <1> 	;		   bit 0 = 0 (invalid buffer)
  2872                              <1> 	;		   bit 1 = 0 (write bit)
  2873                              <1> 	;		   bit 2 = 0 (read bit)	
  2874                              <1>  	;
  2875                              <1> 	;	byte 2 & byte 3 - not used
  2876                              <1> 	;	byte 4 to byte 7 - disk block/sector address
  2877                              <1> 	
  2878                              <1> 	; 04/02/2022
  2879 00005460 50                  <1> 	push	eax
  2880 00005461 E896000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2881 00005466 58                  <1> 	pop	eax
  2882 00005467 730D                <1> 	jnc	short seta ; 14/07/2022
  2883                              <1> 	
  2884                              <1> 	; 14/07/2022
  2885                              <1> 	; (invalidate buffer)
  2886                              <1> 	
  2887                              <1> 	; 02/07/2015 (32 bit modification)
  2888                              <1> 	; 20/07/2013
  2889 00005469 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2890                              <1>        		; mov $-1,2(r1) / destroy associativity
  2891 00005470 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2892                              <1> 		; clrb 1(r1) / do not do I/O
  2893                              <1> 	;stc
  2894 00005475 C3                  <1> 	retn
  2895                              <1>         	; rts r0
  2896                              <1> seta: 
  2897 00005476 C6430101            <1> 	mov	byte [ebx+1], 1 ; clear write/read bits, set valid bit
  2898                              <1> 	;clc
  2899 0000547A C3                  <1> 	retn
  2900                              <1> 
  2901                              <1> %if 0
  2902                              <1> 
  2903                              <1> poke:
  2904                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2905                              <1> 	; 24/10/2015
  2906                              <1> 	; 20/08/2015
  2907                              <1> 	; 18/08/2015
  2908                              <1> 	; 02/07/2015
  2909                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2910                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2911                              <1> 	;
  2912                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2913                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2914                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2915                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2916                              <1> 	;
  2917                              <1> 	; Basic I/O functions for all block structured devices
  2918                              <1> 	;
  2919                              <1>         ; (Modified registers: ECX, EDX, ESI, EDI)
  2920                              <1> 	;
  2921                              <1> 	; 20/07/2013 modifications
  2922                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2923                              <1> 	; INPUTS -> 
  2924                              <1> 	;        (EBX = buffer header address)
  2925                              <1> 	; OUTPUTS ->
  2926                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2927                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2928                              <1> 	;		(drive not ready or r/w error!)
  2929                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2930                              <1> 	;	 (dword [EBX+4] = 0FFFFFFFFh means RW/IO error)
  2931                              <1> 	;        (also it indicates invalid buffer data)
  2932                              <1> 	;
  2933                              <1> 	push	ebx
  2934                              <1>        		; mov r1,-(sp)
  2935                              <1>        		; mov r2,-(sp)
  2936                              <1>        		; mov r3,-(sp)
  2937                              <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2938                              <1> 	;
  2939                              <1> 	; 09/06/2015
  2940                              <1> 	; (permit read/write after a disk R/W error)
  2941                              <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2942                              <1> 	mov	al, 1
  2943                              <1> 	shl	al, cl
  2944                              <1> 	test 	al, [active] ; busy ? (error)
  2945                              <1> 	jz	short poke_0
  2946                              <1> 	not	al
  2947                              <1> 	and	[active], al ; reset busy bit for this device only
  2948                              <1> poke_0:
  2949                              <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2950                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2951                              <1> 					 ; / I/O queue pointer
  2952                              <1> poke_1: ; 1:
  2953                              <1>         sub	esi, 4
  2954                              <1> 	mov	ebx, [esi]
  2955                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2956                              <1> 	mov	ax, [ebx] ; 17/07/2013
  2957                              <1>        	test	ah, 06h
  2958                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2959                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2960                              <1> 			       ; / queue entry
  2961                              <1>         jz      short poke_5
  2962                              <1> 		; beq 2f / branch to 2f if both are clear
  2963                              <1> 	; 31/07/2013
  2964                              <1> 	;test	ah, 0B0h ; (*)
  2965                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2966                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2967                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2968                              <1> 		; bne 2f / branch if any are set
  2969                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2970                              <1>     		; movb (r1),r3 / get device id
  2971                              <1> 	movzx	ecx, al ; 18/08/2015
  2972                              <1> 	;mov	edi, ecx ; 26/04/2013
  2973                              <1> 	xor 	eax, eax ; 0
  2974                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2975                              <1> 		; tstb deverr(r3) / test for errors on this device
  2976                              <1>        	;jna	short poke_2 
  2977                              <1> 		; beq 3f / branch if no errors
  2978                              <1> 	; 02/07/2015
  2979                              <1> 	;dec	eax
  2980                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2981                              <1>        		; mov $-1,2(r1) / destroy associativity
  2982                              <1> 	;shr	eax, 24
  2983                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2984                              <1> 		; clrb 1(r1) / do not do I/O
  2985                              <1> 	;jmp     short poke_5
  2986                              <1>         ;       ; br 2f
  2987                              <1>                 ; rts r0
  2988                              <1> poke_2: ; 3:
  2989                              <1> 	; 02/07/2015
  2990                              <1> 	inc	cl ; 0FFh -> 0
  2991                              <1> 	jz	short poke_5
  2992                              <1> 	inc	al ; mov ax, 1
  2993                              <1> 	dec	cl
  2994                              <1> 	jz	short poke_3
  2995                              <1> 	; 26/04/2013 Modification
  2996                              <1> 	;inc	al ; mov ax, 1
  2997                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2998                              <1> 	;jz	short poke_3 ; cl = 0
  2999                              <1> 	shl	al, cl ; shl ax, cl
  3000                              <1> poke_3:
  3001                              <1> 	;test	[active], ax
  3002                              <1> 	test	[active], al
  3003                              <1> 		; bit $2,active / test disk busy bit
  3004                              <1> 	jnz     short poke_5
  3005                              <1> 		; bne 2f / branch if bit is set
  3006                              <1> 	;or	[active], ax
  3007                              <1> 	or	[active], al
  3008                              <1> 		; bis $2,active / set disk busy bit
  3009                              <1> 	;push	ax
  3010                              <1> 	; 04/02/2022
  3011                              <1> 	push	eax
  3012                              <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  3013                              <1> 	;mov    [edi+drv.error], ah
  3014                              <1> 	; 04/02/2022
  3015                              <1> 	pop	eax
  3016                              <1> 	;pop	ax
  3017                              <1> 	jnc	short poke_4 ; 20/07/2013
  3018                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  3019                              <1> 	;jna	short poke_4
  3020                              <1> 		; tstb deverr(r3) / test for errors on this device
  3021                              <1>        		; beq 3f / branch if no errors
  3022                              <1> 	; 02/07/2015 (32 bit modification)
  3023                              <1> 	; 20/07/2013
  3024                              <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  3025                              <1>        		; mov $-1,2(r1) / destroy associativity
  3026                              <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  3027                              <1> 		; clrb 1(r1) / do not do I/O
  3028                              <1> 	jmp     short poke_5
  3029                              <1> poke_4:	; 20/07/2013
  3030                              <1> 	; 17/07/2013
  3031                              <1> 	not 	al 
  3032                              <1> 	and	[active], al ; reset, not busy
  3033                              <1> 	; eBX = system I/O buffer header (queue entry) address
  3034                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  3035                              <1> 	mov	ax, [ebx]
  3036                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  3037                              <1>         and	ax, 600h
  3038                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  3039                              <1> 	and 	word [ebx], 0F9FFh
  3040                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  3041                              <1> 	shl	ah, 3
  3042                              <1>        		; rol r3
  3043                              <1>                 ; rol r3
  3044                              <1>                 ; rol r3	
  3045                              <1> 	or	[ebx], ax
  3046                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  3047                              <1> 			   ; bits 12 and 13
  3048                              <1> 	call	idle ; 18/01/2014
  3049                              <1> 	;; sti
  3050                              <1> 	;hlt 	; wait for a hardware interrupt
  3051                              <1> 	;; cli
  3052                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  3053                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  3054                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  3055                              <1> 	; method, this procedure will wait for a time according to
  3056                              <1> 	; multi tasking and time sharing concept.
  3057                              <1> 	;
  3058                              <1> 	; 24/10/2015
  3059                              <1> 	;not	ax 
  3060                              <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  3061                              <1> 	and	[ebx], ax ; clear bits 12 and 13
  3062                              <1> poke_5: ;2:
  3063                              <1>         cmp     esi, bufp
  3064                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  3065                              <1>                             ; / has been scanned
  3066                              <1> 	ja      short poke_1
  3067                              <1>                ; bhi 1b
  3068                              <1> 	; 24/03/2013
  3069                              <1>        		; mov (sp)+,r3
  3070                              <1>        		; mov (sp)+,r2
  3071                              <1>        		; mov (sp)+,r1
  3072                              <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  3073                              <1> 	pop 	ebx
  3074                              <1> 	; 02/07/2015 (32 bit modification)
  3075                              <1> 	; 20/07/2013
  3076                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  3077                              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  3078                              <1> 	;	
  3079                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  3080                              <1> 	; or written succesfully; even if an error occurs while
  3081                              <1> 	; reading to or writing from other buffers. 20/07/2013
  3082                              <1> 	;
  3083                              <1> 	; 09/06/2015
  3084                              <1> 	cmc
  3085                              <1> 	retn
  3086                              <1>                 ; rts r0
  3087                              <1> %endif
  3088                              <1> 
  3089                              <1> bufaloc:
  3090                              <1> 	; 15/07/2022
  3091                              <1> 	; 14/07/2022
  3092                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  3093                              <1> 	; 04/02/2022
  3094                              <1> 	; 20/08/2015
  3095                              <1> 	; 19/08/2015
  3096                              <1> 	; 02/07/2015
  3097                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3098                              <1> 	;	     (32 bit modifications)	
  3099                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  3100                              <1> 	;
  3101                              <1> 	; bufaloc - Block device I/O buffer allocation
  3102                              <1> 	; 
  3103                              <1> 	; INPUTS ->
  3104                              <1> 	;    r1 - block number
  3105                              <1> 	;    cdev - current (block/disk) device number
  3106                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  3107                              <1> 	; OUTPUTS ->
  3108                              <1> 	;    r5 - pointer to buffer allocated
  3109                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  3110                              <1> 	;
  3111                              <1> 	; ((AX = R1)) input/output
  3112                              <1> 	; ((BX = R5)) output
  3113                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  3114                              <1> 	;    zf=1 -> block already in a I/O buffer
  3115                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  3116                              <1> 	;    ((DL = Device ID))
  3117                              <1> 	;    (((DH = 0 or 1)))
  3118                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  3119                              <1> 	;    ((CX and DH will not be used after return)))
  3120                              <1> 
  3121                              <1> 	; 14/07/2022
  3122                              <1> 	;	Modified registers: EBX, ECX, EDX, ESI, EDI
  3123                              <1> 
  3124                              <1> 	;;push 	esi ; ***
  3125                              <1> 		; mov r2,-(sp) / save r2 on stack
  3126                              <1>        		; mov $340,*$ps / set processor priority to 7
  3127                              <1> 		; 20/07/2013
  3128                              <1> 	; 26/04/2013
  3129                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  3130                              <1> 	;mov	edi, rdev  ; offset mdev = offset rdev + 1
  3131                              <1> 	;add	edi, ebx
  3132                              <1> 	; 09/01/2022
  3133 0000547B 0FB63D[E4640000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  3134 00005482 81C7[E6640000]      <1> 	add	edi, rdev
  3135                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  3136                              <1> 			;; EDI points to device id.
  3137 00005488 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  3138                              <1> 	; 11/06/2015
  3139 0000548B 80BB[7E5C0000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  3140 00005492 720F                <1> 	jb	short bufaloc_9
  3141 00005494 C705[4F650000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  3141 0000549C 0000                <1>
  3142 0000549E E93EDCFFFF          <1> 	jmp	error
  3143                              <1> bufaloc_9:
  3144 000054A3 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  3145                              <1> bufaloc_10: ; 02/07/2015
  3146                              <1> 	; 14/07/2022
  3147                              <1> 	;xor 	ebp, ebp ; 0
  3148                              <1> 	;push	ebp ; 0
  3149                              <1>         ;mov	ebp, esp	
  3150 000054A5 31FF                <1> 	xor	edi, edi ; 0	
  3151 000054A7 57                  <1> 	push	edi
  3152                              <1> bufaloc_1: ;1:
  3153                              <1> 		; clr -(sp) / vacant buffer
  3154 000054A8 BE[B8640000]        <1>         mov 	esi, bufp
  3155                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3156                              <1> 			     ; / entrys in buffer area
  3157                              <1> bufaloc_2: ;2:
  3158 000054AD 8B1E                <1> 	mov	ebx, [esi]
  3159                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3160                              <1> 			    ; queue entry into r5
  3161                              <1> 	; 14/07/2022
  3162 000054AF 8B0B                <1> 	mov	ecx, [ebx]	
  3163                              <1> 	;test	word [ebx], 0F600h
  3164                              <1> 	; 15/07/2022
  3165 000054B1 F6C501              <1> 	test	ch, 1 ; valid buffer (content) ?
  3166                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3167 000054B4 7505                <1>         jnz	short bufaloc_3 ; yes
  3168                              <1> 		; bne 3f / branch when 
  3169                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3170                              <1>                        ; / (i.e., buffer busy)
  3171                              <1> 	;mov    [ebp], esi ; pointer to I/0 queue entry
  3172                              <1> 	; 14/07/2022
  3173                              <1> 	; save free buffer pointer 
  3174 000054B6 893424              <1> 	mov	[esp], esi
  3175                              <1>                 ; mov r2,(sp) ;/ save pointer to last non-busy buffer
  3176                              <1> 			; / found points to word 2 of I/O queue entry)
  3177                              <1> 	; continue to see if requested sector/block buffer
  3178                              <1> 	;	already is one of existing (valid) buffers
  3179                              <1> 	;jmp	short bufaloc_4
  3180 000054B9 EB0E                <1> 	jmp	short bufaloc_11 ; 14/07/2022
  3181                              <1> bufaloc_3: ;3:
  3182                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3183                              <1> 	;
  3184 000054BB 38D1                <1> 	cmp	cl, dl ; 14/07/2022
  3185                              <1> 	;cmp	[ebx], dl	
  3186                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3187                              <1> 			       ; / as current device
  3188 000054BD 7508                <1> 	jne	short bufaloc_4
  3189                              <1>        		; bne 3f
  3190 000054BF 394304              <1> 	cmp	[ebx+4], eax
  3191                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3192                              <1> 			     ; / same as current block number
  3193 000054C2 7503                <1>        	jne	short bufaloc_4
  3194                              <1> 		; bne 3f
  3195                              <1> 	;add	esp, 4
  3196 000054C4 59                  <1> 	pop	ecx
  3197                              <1>        		; tst (sp)+ / bump stack pointer
  3198 000054C5 EB1D                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3199                              <1> 				; jump to bufaloc_6 in original Unix v1
  3200                              <1>        		; br 1f / use this buffer
  3201                              <1> bufaloc_4: ;3:
  3202                              <1> 	; 14/07/2022
  3203                              <1> 	; save last valid buffer 
  3204                              <1> 	; (will be used if there is not a free buffer)
  3205 000054C7 89F7                <1> 	mov	edi, esi	
  3206                              <1> bufaloc_11:
  3207 000054C9 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3208                              <1> 	;
  3209 000054CC 81FE[D8640000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3210                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3211 000054D2 72D9                <1> 	jb	short bufaloc_2
  3212                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3213                              <1>                        ; / buffers not checked)
  3214 000054D4 5E                  <1>         pop	esi
  3215                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3216                              <1> 			     ; / to last free block
  3217 000054D5 09F6                <1>        	or	esi, esi 
  3218 000054D7 7502                <1> 	jnz	short bufaloc_5
  3219                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3220                              <1> 	        ; / if a free buffer is found branch to 2f
  3221                              <1> 	
  3222                              <1> 	; 14/07/2022        
  3223                              <1> 	; if there is not a free buffer
  3224                              <1> 	; we can use last valid buffer (the oldest buffer)
  3225                              <1> 	; ((ptr to new buffer is located at head of buff ptr chain))
  3226 000054D9 89FE                <1> 	mov	esi, edi
  3227                              <1> 
  3228                              <1> 	;;mov  ecx, [s.wait_]
  3229                              <1> 	;call	idle
  3230                              <1> 	;	; jsr r0,idle; s.wait+2 / idle if no free buffers
  3231                              <1> 	;jmp 	short bufaloc_10 ; 02/07/2015
  3232                              <1>        	;	; br 1b
  3233                              <1> bufaloc_5: ;2:
  3234                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3235                              <1> 	; 14/07/2022
  3236                              <1> 	;inc	dh ; Retro UNIX 8086 v1 modification
  3237                              <1> bufaloc_6: ;1:
  3238 000054DB 8B1E                <1>         mov    	ebx, [esi] 
  3239                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3240                              <1> 			     ; / entry in r5
  3241                              <1> 	;; 26/04/2013
  3242                              <1>         ;;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3243                              <1> 	;mov 	[ebx], dl
  3244                              <1> 		; movb cdev,(r5) / put current device number 
  3245                              <1> 				 ; / in I/O queue entry
  3246                              <1> 	; 14/07/2022
  3247                              <1> 	; invalidate buffer before r/w (new) disk sector/block
  3248                              <1> 	;mov	[ebx+1], dh ; 0
  3249                              <1> 	; 14/07/2022
  3250 000054DD 8913                <1> 	mov	[ebx], edx  ; dh = 0
  3251                              <1> 	
  3252 000054DF 894304              <1> 	mov 	[ebx+4], eax
  3253                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3254                              <1> 			     ; / of I/O queue entry
  3255                              <1> 	; 14/07/2022
  3256 000054E2 FEC6                <1> 	inc	dh ; dh = 1
  3257                              <1> bufaloc_7: ;1:
  3258 000054E4 81FE[B8640000]      <1>         cmp	esi, bufp
  3259                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3260                              <1> 			     ; / and put latest assigned
  3261 000054EA 760B                <1> 	jna	short bufaloc_8	
  3262                              <1>        		; blos 1f / buffer on the top 
  3263                              <1> 			; / (this makes if the lowest priority)
  3264                              <1> 	; 14/07/2022
  3265 000054EC 89F7                <1> 	mov	edi, esi
  3266 000054EE 83EE04              <1> 	sub	esi, 4
  3267 000054F1 8B0E                <1> 	mov	ecx, [esi]
  3268 000054F3 890F                <1> 	mov	[edi], ecx ; 14/07/2022
  3269                              <1> 	;mov	[esi+4], ecx
  3270                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3271 000054F5 EBED                <1> 	jmp 	short bufaloc_7        
  3272                              <1> 		; br 1b
  3273                              <1> bufaloc_8: ;1:
  3274 000054F7 891E                <1>         mov	[esi], ebx
  3275                              <1> 		; mov r5,(r2)
  3276                              <1> 	;;pop	esi ; ***
  3277                              <1>        		; mov (sp)+,r2 / restore r2
  3278 000054F9 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3279                              <1> 		; Retro UNIX 8086 v1 modification
  3280                              <1> 		; zf=1 --> block already is in an I/O buffer
  3281                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3282 000054FB C3                  <1> 	retn
  3283                              <1> 		; rts r0
  3284                              <1> 
  3285                              <1> diskio:
  3286                              <1> 	; 12/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.21)
  3287                              <1> 	; ((Ref: Retro UNIX 386 v1.1 'diskio' modification: 12/07/2022))
  3288                              <1> 	; 
  3289                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3290                              <1> 	;	((simplified and shortened 'diskio.s' code)
  3291                              <1> 	;
  3292                              <1> 	; 12/02/2022
  3293                              <1> 	; 04/02/2022 (Retro UNIX 386 v1 2022, Kernel v0.2.0.18)
  3294                              <1> 	; 10/07/2015
  3295                              <1> 	; 02/07/2015
  3296                              <1> 	; 16/06/2015
  3297                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3298                              <1> 	;	     (80386 protected mode modifications)	
  3299                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3300                              <1> 	;
  3301                              <1> 	; Retro UNIX 8086 v1 feature only !
  3302                              <1> 	;
  3303                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3304                              <1> 	; 04/07/2009 - 20/07/2011
  3305                              <1> 	;
  3306                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3307                              <1> 	;
  3308                              <1>         ; INPUTS ->
  3309                              <1> 	; 	   EBX = System I/O Buffer header address
  3310                              <1> 	;
  3311                              <1>         ; OUTPUTS -> cf=0 --> done 
  3312                              <1> 	; 	     cf=1 --> error code in AH
  3313                              <1> 	;
  3314                              <1> 	; (Modified registers: EAX, ECX, EDX)
  3315                              <1> 	
  3316                              <1> ;rw_disk_sector:
  3317                              <1> 	; 12/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.21)
  3318                              <1> 	; 12/02/2022
  3319                              <1> 	; 10/07/2015
  3320                              <1> 	; 02/07/2015
  3321                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3322                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3323                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3324                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3325                              <1> 	;
  3326                              <1> 	;;mov	dx, 0201h ; Read 1 sector/block
  3327                              <1> 	;mov	dh, 2
  3328                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3329 000054FC B602                <1> 	mov	dh, 2 ; Write 1 sector/block
  3330 000054FE 668B03              <1> 	mov	ax, [ebx]
  3331                              <1> 	;
  3332 00005501 56                  <1> 	push	esi ; ****
  3333 00005502 53                  <1> 	push	ebx ; ***
  3334                              <1> 	;
  3335 00005503 0FB6C8              <1> 	movzx	ecx, al
  3336 00005506 89CE                <1> 	mov	esi, ecx
  3337                              <1> 	;
  3338 00005508 38F1                <1> 	cmp	cl, dh ; 2
  3339 0000550A 7202                <1> 	jb	short rwdsk0
  3340 0000550C 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3341                              <1> rwdsk0:
  3342                              <1> 	; 12/07/2022
  3343                              <1> 	;mov	[drv], al
  3344 0000550E 81C6[7E5C0000]      <1> 	add	esi, drv.status
  3345                              <1> 	; 11/06/2015
  3346 00005514 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3347 00005517 7204                <1> 	jb      short rwdsk1
  3348                              <1> 	; 'drive not ready' error
  3349                              <1> 	; 12/02/2022
  3350                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3351                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3352                              <1> 	;;jmp	error
  3353                              <1> 	;stc	; cf = 1
  3354                              <1> 	;retn
  3355                              <1> 	; 12/02/2022
  3356 00005519 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3357 0000551B EB1F                <1> 	jmp	short rwdsk_err1
  3358                              <1> rwdsk1:
  3359                              <1> 	;test	ah, 2
  3360                              <1> 	;;test	ax, 200h ; Bit 9 of word 0 (status word)
  3361                              <1> 	;		 ; write bit
  3362                              <1> 	;jz	short rwdsk2
  3363                              <1> 	
  3364                              <1> 	;;test	ah, 4
  3365                              <1> 	;;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3366                              <1> 	;;		 ; read bit
  3367                              <1> 	;;jz	short diskio_ret
  3368                              <1> 
  3369                              <1> 	;inc	dh ; 03h = write
  3370                              <1> 
  3371                              <1> 	; 08/07/2022
  3372 0000551D 84F4                <1> 	test	ah, dh ; test ah, 2
  3373 0000551F 7502                <1> 	jnz	short rwdsk2 ; dh = 02h = write
  3374 00005521 FECE                <1> 	dec	dh
  3375                              <1> 		; dh = 01h = read
  3376                              <1> rwdsk2:
  3377 00005523 88C2                <1> 	mov	dl, al
  3378 00005525 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3379 00005528 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3380 0000552A C0E102              <1> 	shl	cl, 2
  3381 0000552D 81C1[625C0000]      <1> 	add	ecx, drv.size ; disk size
  3382 00005533 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3383 00005535 7214                <1> 	jb      short rwdsk3
  3384                              <1>  	; 'out of volume' error
  3385                              <1> 	; 12/02/2022
  3386                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3387                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3388                              <1> 	;;jmp	error
  3389                              <1> 	;stc	; cf = 1
  3390                              <1> 	;retn
  3391                              <1> 	; 12/02/2022
  3392 00005537 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3393                              <1> rwdsk_err1:
  3394 0000553C C605[62650000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3395 00005543 890D[4F650000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3396 00005549 EB27                <1> 	jmp	short rwdsk_err2
  3397                              <1> rwdsk3:
  3398                              <1> 	; 11/06/2015
  3399 0000554B 83C304              <1> 	add	ebx, 4 ; buffer address
  3400 0000554E C605[7E650000]04    <1> 	mov	byte [retry_count], 4
  3401                              <1> 	; 12/07/2022
  3402                              <1> 	;test	byte [esi], 1 ; LBA ready ?
  3403                              <1>         ;jz	short rwdsk_chs
  3404                              <1> rwdsk_lba:
  3405                              <1> 	; LBA read/write (with private LBA function) 
  3406                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3407 00005555 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3408 00005558 89C1                <1> 	mov	ecx, eax ; sector number
  3409                              <1> 	; ebx = buffer (data) address
  3410                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3411                              <1> rwdsk_lba_retry:
  3412                              <1> 	;mov	dl, [drv]
  3413                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3414                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3415                              <1> 	;;mov	ah, 1Ch - 03h ; LBA write function number - 3
  3416                              <1> 	;mov	ah, 2 ; LBA write function number - 2
  3417                              <1> 	;add	ah, dh		
  3418                              <1> 	;mov	al, 1
  3419                              <1> 	;int	13h
  3420                              <1> 	;call	int13h
  3421                              <1> 	; 12/07/2022
  3422 0000555A 88F0                <1> 	mov	al, dh	; function (1 or 2)
  3423                              <1> 			; (1 = read, 2 = write )
  3424                              <1> 	; ecx = disk sector address (LBA)
  3425                              <1> 	; ebx = buffer address
  3426                              <1> 	;  dl = (physical) disk number
  3427                              <1> 	;  al = function (r/w)
  3428 0000555C E80DCAFFFF          <1> 	call	DISK_IO
  3429                              <1> 
  3430 00005561 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3431 00005563 730E                <1> 	jnc	short rwdsk_lba_ok
  3432 00005565 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3433 00005568 7408                <1>         je      short rwdsk_lba_fails
  3434 0000556A FE0D[7E650000]      <1> 	dec	byte [retry_count]
  3435 00005570 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3436                              <1> rwdsk_err2:	; 12/02/2022
  3437                              <1> rwdsk_lba_fails:
  3438 00005572 F9                  <1> 	stc
  3439                              <1> rwdsk_lba_ok:
  3440 00005573 5B                  <1> 	pop	ebx ; ***
  3441 00005574 5E                  <1> 	pop	esi ; ****
  3442 00005575 C3                  <1> 	retn
  3443                              <1> rwdsk_lba_reset:
  3444                              <1> 	;mov	ah, 0Dh ; Alternate reset
  3445                              <1> 	;int	13h
  3446                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3447                              <1> 	;mov	ah, 5 ; Alternate reset	 
  3448                              <1> 	;call	int13h
  3449                              <1> 	;jnc	short rwdsk_lba_retry
  3450                              <1> 	; 12/07/2022
  3451 00005576 30C0                <1> 	xor	al, al ; 0 ; reset
  3452 00005578 E8F1C9FFFF          <1> 	call	DISK_IO
  3453 0000557D 73DB                <1> 	jnc	short rwdsk_lba_retry
  3454                              <1> 
  3455 0000557F 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3456 00005581 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3457                              <1> 
  3458                              <1> 	; 12/07/2022 
  3459                              <1> 	;	(CHS Read/Write setup is not needed here.)
  3460                              <1> 	; 	(LBA address will be converted to CHS parameters
  3461                              <1> 	;	in 'DISK_IO' procedure when/if it is required.)
  3462                              <1> 	
  3463                              <1> ;	; CHS read (convert LBA address to CHS values)	
  3464                              <1> ;rwdsk_chs:
  3465                              <1> ;	; 10/07/2015
  3466                              <1> ;	sub	esi, drv.status
  3467                              <1> ;	mov	ecx, esi
  3468                              <1> ;	add 	esi, drv.error
  3469                              <1> ;	; 02/07/2015
  3470                              <1> ;	; 16/06/2015
  3471                              <1> ;	; 11/06/2015 
  3472                              <1> ;	push	ebx ; ** ; buffer
  3473                              <1> ;	shl	ecx, 1
  3474                              <1> ;	push	ecx ; * 
  3475                              <1> ;	;
  3476                              <1> ;	mov	ebx, ecx
  3477                              <1> ;	mov	[rwdsk], dh ; 02/07/2015
  3478                              <1> ;	xor	edx, edx ; 0
  3479                              <1> ;	; 04/02/2022
  3480                              <1> ;	;sub	ecx, ecx 
  3481                              <1> ;	add     ebx, drv.spt
  3482                              <1> ;	mov	cx, [ebx] ; sector per track
  3483                              <1> ;		; EDX:EAX = LBA
  3484                              <1> ;	div	ecx
  3485                              <1> ;	mov	cl, dl	; sector number - 1
  3486                              <1> ;	inc	cl	; sector number (1 based)
  3487                              <1> ;	pop	ebx ; * ; 11/06/2015
  3488                              <1> ;	;push	cx
  3489                              <1> ;	; 04/02/2022
  3490                              <1> ;	push	ecx
  3491                              <1> ;	add     ebx, drv.heads
  3492                              <1> ;	mov	cx, [ebx] ; heads
  3493                              <1> ;	xor	edx, edx
  3494                              <1> ;		; EAX = cylinders * heads + head
  3495                              <1> ;	div	ecx
  3496                              <1> ;	;pop	cx     ; sector number
  3497                              <1> ;	; 04/02/2022
  3498                              <1> ;	pop	ecx
  3499                              <1> ;	mov	dh, dl ; head number
  3500                              <1> ;	mov	dl, [drv]
  3501                              <1> ;	mov	ch, al ; cylinder (bits 0-7)
  3502                              <1> ;	shl	ah, 6
  3503                              <1> ;	or	cl, ah ; cylinder (bits 8-9)
  3504                              <1> ;		       ; sector (bits 0-7)
  3505                              <1> ;	pop	ebx ; ** ; buffer ; 11/06/2015
  3506                              <1> ;		; CL = sector (bits 0-5)
  3507                              <1> ;		;      cylinder (bits 8-9 -> bits 6-7)
  3508                              <1> ;		; CH = cylinder (bits 0-7)
  3509                              <1> ;		; DH = head
  3510                              <1> ;		; DL = drive
  3511                              <1> ;	;
  3512                              <1> ;	mov	byte [retry_count], 4
  3513                              <1> ;rwdsk_retry:	
  3514                              <1> ;	;mov	ah, [rwdsk] ; 02h = read, 03h = write
  3515                              <1> ;	; 08/07/2022
  3516                              <1> ;	mov	ah, [rwdsk] ; 01h = read, 02h = write
  3517                              <1> ;	mov	al, 1 ; sector count	
  3518                              <1> ;	;int	13h
  3519                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3520                              <1> ;	call	int13h
  3521                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3522                              <1> ;	jnc	short rwdsk_ok ; ah = 0
  3523                              <1> ;	cmp	ah, 80h ; time out ?
  3524                              <1> ;	je	short rwdsk_fails
  3525                              <1> ;	dec	byte [retry_count]
  3526                              <1> ;	jnz	short rwdsk_reset
  3527                              <1> ;rwdsk_fails:
  3528                              <1> ;	stc
  3529                              <1> ;rwdsk_ok:
  3530                              <1> ;	pop	ebx ; ***
  3531                              <1> ;	pop	esi ; ****
  3532                              <1> ;	retn
  3533                              <1> ;rwdsk_reset:
  3534                              <1> ;	; 02/02/2015
  3535                              <1> ;	sub	ah, ah
  3536                              <1> ;	cmp	dl, 80h
  3537                              <1> ;	jb	short rwdsk_fd_reset
  3538                              <1> ;	;mov	ah, 0Dh ; Alternate reset
  3539                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3540                              <1> ;	mov	ah, 5  ; Alternate reset
  3541                              <1> ;rwdsk_fd_reset:
  3542                              <1> ;	;int	13h
  3543                              <1> ;	call	int13h
  3544                              <1> ;	jnc	short rwdsk_retry
  3545                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3546                              <1> ;	jmp 	short rwdsk_ok
  3547                              <1> 
  3548                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3549                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3550                              <1> ;
  3551                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3552                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3553                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3554                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3555                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3556                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3557                              <1> ; as in original unix v1.
  3558                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3559                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3560                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3561                              <1> ;
  3562                              <1> ; Erdogan tan (10/07/2015) 
  3563                              <1> 
  3564                              <1> ;drum: / interrupt handler
  3565                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3566                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3567                              <1> ;                                      / error
  3568                              <1> ;               br 3f / no, error
  3569                              <1> ;       br      2f / error
  3570                              <1> ;
  3571                              <1> ;disk:
  3572                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3573                              <1> ;       jmp     *$0f
  3574                              <1> ;0:
  3575                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3576                              <1> ;      	        br 3f / no, errors
  3577                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3578                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3579                              <1> ;                        / to 1f
  3580                              <1> ;       br      4f
  3581                              <1> ;1:
  3582                              <1> ;       bit     $20000,rkcs
  3583                              <1> ;       beq     4f / wait for seek complete
  3584                              <1> ;       mov     $0b,0b-2
  3585                              <1> ;       mov     rkap,r1
  3586                              <1> ;2:
  3587                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3588                              <1> ;                          / the disk buffer
  3589                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3590                              <1> ;       inc     r1
  3591                              <1> ;       asr     (r1)
  3592                              <1> ;       asr     (r1)
  3593                              <1> ;       asr     (r1) / reissue request
  3594                              <1> ;       dec     r1
  3595                              <1> ;3:
  3596                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3597                              <1> ;       mov     ac,-(sp)
  3598                              <1> ;       mov     mq,-(sp) / put these on the stack
  3599                              <1> ;       mov     sc,-(sp)
  3600                              <1> ;       jsr     r0,poke
  3601                              <1> ;       mov     (sp)+,sc
  3602                              <1> ;       mov     (sp)+,mq / pop them off stack
  3603                              <1> ;       mov     (sp)+,ac
  3604                              <1> ;4:
  3605                              <1> ;       jmp     retisp / u4-3
  3606                              <1> ;
  3607                              <1> ;trapt:                  / r2 points to the
  3608                              <1> ;       mov     (r0)+,r2 / device control register
  3609                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3610                              <1> ;       tst     (sp)+
  3611                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3612                              <1> ;       bge     4b / device still active so branch
  3613                              <1> ;       bit     (r0),active / was device busy?
  3614                              <1> ;       beq     4b / no, stray interrupt
  3615                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3616                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3617                              <1> ;       bge     2f / if no error jump to 2f
  3618                              <1> ;       tst     (r0)+ / skip on error
  3619                              <1> ; 2:
  3620                              <1> ;       jmp     (r0)
  2060                                  %include 'u9.s'        ; 29/06/2015
  2061                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS9.INC
  2062                              <1> ; Last Modification: 13/06/2022
  2063                              <1> ; ----------------------------------------------------------------------------
  2064                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2065                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2066                              <1> ;
  2067                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2068                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2069                              <1> ; <Bell Laboratories (17/3/1972)>
  2070                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2071                              <1> ;
  2072                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2073                              <1> ;
  2074                              <1> ; ****************************************************************************
  2075                              <1> ; 21/11/2015
  2076                              <1> 
  2077                              <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) - Printer BIOS (Functions)
  2078                              <1> ; 04/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2079                              <1> ; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2080                              <1> 
  2081                              <1> getch:
  2082                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2083                              <1> 	; 30/06/2015
  2084                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2085 00005583 28C0                <1> 	sub	al, al ; 0
  2086                              <1> getch_q: ; 06/08/2015
  2087 00005585 8A25[66610000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2088 0000558B EB06                <1>         jmp     short getc_n
  2089                              <1> 
  2090                              <1> getc: 
  2091                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2092                              <1> 	; 12/11/2015
  2093                              <1> 	; 15/09/2015
  2094                              <1> 	; 01/07/2015
  2095                              <1> 	; 30/06/2015
  2096                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2097                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2098                              <1> 	;
  2099                              <1> 	; Retro UNIX 8086 v1 modification !
  2100                              <1> 	; 
  2101                              <1> 	; 'getc' gets (next) character 
  2102                              <1> 	;	 from requested TTY (keyboard) buffer 
  2103                              <1> 	; INPUTS ->
  2104                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2105                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2106                              <1> 	;	(Keyboard buffer will point to 
  2107                              <1> 	;			next character at next call)
  2108                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2109                              <1> 	;	(Keyboard buffer will point to 
  2110                              <1> 	;			current character at next call)
  2111                              <1> 	; OUTPUTS ->
  2112                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2113                              <1> 	;     			 ZF=0 -> AX has (current) character
  2114                              <1> 	;      AL = ascii code
  2115                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2116                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2117                              <1> 	; Original UNIX V1 'getc': 
  2118                              <1> 	;		get a character off character list
  2119                              <1> 	;
  2120                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2121                              <1> 	;
  2122                              <1> 	; 30/06/2015 (32 bit modifications)
  2123                              <1> 	; 16/07/2013
  2124                              <1> 	; mov 	[getctty], ah
  2125                              <1> 	;
  2126                              <1> 
  2127 0000558D 8A25[4E650000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2128                              <1> getc_n:
  2129                              <1> 	; 30/06/2015
  2130 00005593 08E4                <1> 	or	ah, ah
  2131 00005595 740D                <1> 	jz	short getc0 
  2132 00005597 D0E4                <1> 	shl	ah, 1
  2133 00005599 0FB6DC              <1> 	movzx	ebx, ah
  2134 0000559C 81C3[68610000]      <1> 	add	ebx, ttychr
  2135 000055A2 EB05                <1> 	jmp	short getc1
  2136                              <1> getc0:
  2137 000055A4 BB[68610000]        <1> 	mov	ebx, ttychr
  2138                              <1> getc1:
  2139 000055A9 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2140                              <1> 				; (by kb_int)	
  2141 000055AC 6609C9              <1> 	or	cx, cx
  2142 000055AF 7507                <1> 	jnz	short getc2
  2143 000055B1 20C0                <1> 	and 	al, al
  2144 000055B3 7415                <1> 	jz	short getc_s
  2145                              <1> 	;xor	ax, ax
  2146                              <1> 	; 24/12/2021
  2147 000055B5 31C0                <1> 	xor	eax, eax
  2148 000055B7 C3                  <1> 	retn
  2149                              <1> getc2:	
  2150 000055B8 20C0                <1> 	and	al, al
  2151 000055BA 6689C8              <1> 	mov	ax, cx
  2152 000055BD 66B90000            <1> 	mov	cx, 0
  2153 000055C1 7506                <1> 	jnz	short getc3
  2154                              <1> getc_sn:
  2155 000055C3 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2156 000055C6 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2157                              <1> getc3:
  2158 000055C9 C3                  <1> 	retn
  2159                              <1> getc_s:
  2160                              <1> 	; 12/11/2015
  2161                              <1> 	; 15/09/2015
  2162                              <1> 	; 01/07/2015
  2163                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2164                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2165                              <1> 	;
  2166                              <1> 	; tty  of the current process is not 
  2167                              <1> 	; current tty (ptty); so, current process only 
  2168                              <1> 	; can use keyboard input when its tty becomes 
  2169                              <1> 	; current tty (ptty).
  2170                              <1> 	; 'sleep' is for preventing an endless lock
  2171                              <1> 	; during this tty input request.
  2172                              <1> 	; (Because, the user is not looking at the video page
  2173                              <1> 	; of the process to undersand there is a keyboard
  2174                              <1> 	; input request.)
  2175                              <1> 	;
  2176                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2177                              <1> 	;
  2178                              <1> 	; 05/10/2013
  2179                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2180                              <1> 	;
  2181                              <1> 	; 10/10/2013
  2182                              <1> gcw0:
  2183 000055CA B10A                <1> 	mov	cl, 10 ; ch = 0
  2184                              <1> gcw1:	
  2185                              <1> 	; 12/11/2015
  2186 000055CC E814DCFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2187                              <1> 	; 10/10/2013
  2188 000055D1 E8B2EFFFFF          <1> 	call	idle
  2189 000055D6 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2190                              <1> 				; (by kb_int)
  2191 000055D9 6609C0              <1> 	or	ax, ax
  2192                              <1> ;	jnz	short gcw3
  2193 000055DC 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2194                              <1> 	; 30/06/2015
  2195 000055DE FEC9                <1> 	dec	cl
  2196 000055E0 75EA                <1> 	jnz	short gcw1
  2197                              <1> 	;
  2198 000055E2 8A25[4E650000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2199                              <1> ;	; 10/12/2013
  2200                              <1> ;	cmp 	ah, [ptty]
  2201                              <1> ;	jne	short gcw2
  2202                              <1> ;	; 14/02/2014
  2203                              <1> ;	cmp	byte [u.uno], 1
  2204                              <1> ;	jna	short gcw0		
  2205                              <1> ;gcw2:
  2206 000055E8 E828F0FFFF          <1> 	call	sleep
  2207                              <1> 	;
  2208                              <1> 	; 20/09/2013
  2209 000055ED 8A25[4E650000]      <1> 	mov	ah, [u.ttyn]
  2210 000055F3 30C0                <1> 	xor 	al, al
  2211 000055F5 EB9C                <1> 	jmp	short getc_n
  2212                              <1> ;gcw3:
  2213                              <1> gcw2: 	; 15/09/2015
  2214                              <1> 	; 10/10/2013
  2215 000055F7 30C9                <1> 	xor	cl, cl
  2216 000055F9 EBC8                <1> 	jmp	short getc_sn
  2217                              <1> 
  2218                              <1> putc:	
  2219                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2220                              <1> 	; 13/08/2015
  2221                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2222                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2223                              <1> 	;
  2224                              <1> 	; Retro UNIX 8086 v1 modification !
  2225                              <1> 	; 
  2226                              <1> 	; 'putc' puts a character 
  2227                              <1> 	;	 onto requested (tty) video page or
  2228                              <1> 	;	 serial port
  2229                              <1> 	; INPUTS ->
  2230                              <1> 	;     AL = ascii code of the character
  2231                              <1> 	;     AH = video page (tty) number (0 to 7)
  2232                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2233                              <1> 	; OUTPUTS ->
  2234                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2235                              <1> 	;      			ZF=0 -> AX has (current) character
  2236                              <1> 	;     cf=0 and AH = 0 -> no error
  2237                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2238                              <1> 	; 
  2239                              <1> 	; Original UNIX V1 'putc': 
  2240                              <1> 	;     put a character at the end of character list
  2241                              <1> 	;
  2242                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2243                              <1> 	;
  2244 000055FB 80FC07              <1> 	cmp	ah, 7
  2245                              <1>         ;ja	sndc
  2246 000055FE 770A                <1>         ja      short sndc ; 24/12/2024
  2247                              <1> 	; 30/06/2015
  2248 00005600 0FB6DC              <1> 	movzx	ebx, ah
  2249                              <1> 	; 13/08/2015
  2250 00005603 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2251 00005605 E9ABBCFFFF          <1> 	jmp	write_tty ; 'video.inc'
  2252                              <1> 
  2253                              <1> sndc:   ; <Send character>
  2254                              <1> 	;
  2255                              <1> 	; 12/01/2022
  2256                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2257                              <1> 	; 17/11/2015
  2258                              <1> 	; 16/11/2015
  2259                              <1> 	; 11/11/2015
  2260                              <1> 	; 10/11/2015
  2261                              <1> 	; 09/11/2015
  2262                              <1> 	; 08/11/2015
  2263                              <1> 	; 07/11/2015
  2264                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2265                              <1> 	; 29/10/2015
  2266                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2267                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2268                              <1> 	;
  2269                              <1> 	; Retro UNIX 8086 v1 feature only !
  2270                              <1> 	;
  2271                              <1> 	; ah = [u.ttyn]
  2272                              <1> 	;
  2273                              <1> 	; 30/06/2015
  2274 0000560A 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2275                              <1> 	; 07/11/2015
  2276 0000560D 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2277                              <1> sndc0:
  2278                              <1> 	; 07/11/2015
  2279 00005610 E84EF0FFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2280 00005615 7405                <1> 	jz	short sndc1
  2281 00005617 E8C9DBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2282                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2283                              <1> sndc1:
  2284                              <1> 	; 16/11/2015
  2285                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2286                              <1> 	; 24/12/2021
  2287 0000561C 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2288                              <1> sndcx:
  2289 0000561E 8A83[AA610000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2290 00005624 8AA3[A8610000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2291                              <1> 	;
  2292                              <1> 	; 17/11/2015
  2293                              <1> 	; check 'request for response' status
  2294 0000562A 80BB[A4610000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2295 00005631 740A                <1> 	jz	short query
  2296                              <1> response:
  2297 00005633 FE05[A7610000]      <1> 	inc 	byte [comqr] ; query or response status
  2298 00005639 B0FF                <1> 	mov	al, 0FFh	 
  2299 0000563B EB14                <1> 	jmp	short sndc3
  2300                              <1> query:
  2301 0000563D 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2302 0000563F 750E                <1> 	jnz 	short sndc2 ; normal character
  2303                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2304                              <1> 	;je	short sndc2  ; yes, already responded
  2305                              <1> 	; 16/11/2015
  2306                              <1> 	; query: request for response (again)
  2307 00005641 8883[A8610000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2308 00005647 FE05[A7610000]      <1> 	inc 	byte [comqr] ; query or response status
  2309 0000564D EB02                <1> 	jmp	short sndc3
  2310                              <1> sndc2:
  2311 0000564F 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2312                              <1> sndc3:
  2313 00005651 8883[AA610000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2314 00005657 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2315                              <1> 	; 30/06/2015
  2316 00005659 E839D5FFFF          <1> 	call	sp_status ; get serial port status
  2317                              <1> 	; AL = Line status, AH = Modem status
  2318                              <1> 	; 07/11/2015
  2319 0000565E A880                <1> 	test	al, 80h
  2320 00005660 7504                <1> 	jnz	short sndc4
  2321 00005662 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2322 00005664 751A                <1> 	jnz	short sndc5
  2323                              <1> sndc4: 	; Check line status again
  2324                              <1> 	; 16/11/2015
  2325                              <1> 	;push	cx
  2326                              <1> 	; 24/12/2021
  2327 00005666 51                  <1> 	push	ecx
  2328                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2329                              <1> 	; 12/01/2022
  2330 00005667 31C9                <1> 	xor	ecx, ecx
  2331 00005669 B106                <1> 	mov	cl, 6
  2332 0000566B E83CBDFFFF          <1> 	call	WAITF
  2333                              <1> 	;pop	cx
  2334                              <1> 	; 24/12/1021
  2335 00005670 59                  <1> 	pop	ecx
  2336                              <1> 	;
  2337 00005671 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2338 00005673 E81FD5FFFF          <1> 	call	sp_status ; get serial port status
  2339                              <1> 	; 16/11/2015
  2340                              <1> 	; 09/11/2015
  2341                              <1> 	; 08/11/2015
  2342 00005678 A880                <1> 	test	al, 80h	; time out error
  2343 0000567A 7565                <1>         jnz     short sndc7
  2344 0000567C A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2345 0000567E 7461                <1>         jz	short sndc7
  2346                              <1> sndc5:  
  2347 00005680 8A83[AA610000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2348 00005686 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2349 0000568A 28DE                <1> 	sub	dh, bl
  2350 0000568C EE                  <1> 	out	dx, al	   ; send on serial port
  2351                              <1> 	; 10/11/2015
  2352                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2353                              <1> 	; (to improve text flow to the terminal)
  2354                              <1> 	; ('diskette.inc': 'WAITF')
  2355                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2356                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2357                              <1> 	;push	cx
  2358                              <1> 	; 24/12/2021
  2359 0000568D 51                  <1> 	push	ecx
  2360                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2361                              <1> 	; 12/01/2022
  2362 0000568E 29C9                <1> 	sub	ecx, ecx
  2363 00005690 B106                <1> 	mov	cl, 6
  2364 00005692 E815BDFFFF          <1> 	call	WAITF
  2365                              <1> 	;pop	cx
  2366                              <1> 	; 24/12/1021
  2367 00005697 59                  <1> 	pop	ecx
  2368                              <1>     	;
  2369                              <1> 	; 07/11/2015
  2370 00005698 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2371                              <1> 	;
  2372 0000569A E8F8D4FFFF          <1> 	call	sp_status ; get serial port status
  2373                              <1> 	; AL = Line status, AH = Modem status
  2374                              <1> 	;
  2375 0000569F E8BFEFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2376 000056A4 7405                <1> 	jz	short sndc6
  2377 000056A6 E83ADBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2378                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2379                              <1> sndc6:
  2380 000056AB 3C80                <1> 	cmp	al, 80h
  2381 000056AD 7332                <1> 	jnb	short sndc7		
  2382                              <1> 	;
  2383 000056AF 803D[A7610000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2384 000056B6 7244                <1> 	jb	short sndc8 	; no, normal character
  2385 000056B8 883D[A7610000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2386                              <1> 	; 17/11/2015
  2387 000056BE E8C5EEFFFF          <1> 	call	idle
  2388                              <1> 	;
  2389 000056C3 38BB[AA610000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2390                              <1>         ;ja	sndc2       ; response (will be followed by
  2391                              <1> 			    ; a normal character)
  2392                              <1> 	; 24/12/2021
  2393 000056C9 7602                <1> 	jna	short sndc_10
  2394 000056CB EB82                <1> 	jmp	sndc2
  2395                              <1> sndc_10:
  2396                              <1> 	; Query request must be responded by the terminal
  2397                              <1> 	; before sending a normal character !
  2398 000056CD 53                  <1> 	push	ebx
  2399                              <1> 	;push	cx ; *** cl = character (to be sent)
  2400                              <1> 	; 24/12/2021
  2401 000056CE 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2402 000056CF 8A25[4E650000]      <1> 	mov	ah, [u.ttyn]
  2403 000056D5 E83BEFFFFF          <1> 	call	sleep ; this process will be awakened by
  2404                              <1> 		      ; received data available interrupt
  2405                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2406                              <1> 	; 24/12/2021
  2407 000056DA 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2408 000056DB 5B                  <1> 	pop	ebx
  2409 000056DC E93DFFFFFF          <1>         jmp	sndcx
  2410                              <1> sndc7:
  2411                              <1> 	 ; 16/11/2015
  2412 000056E1 803D[A7610000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2413 000056E8 7213                <1> 	jb	short sndc9 	; no
  2414                              <1> 	;
  2415 000056EA 88BB[A8610000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2416 000056F0 88BB[AA610000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2417                              <1> 	;
  2418 000056F6 883D[A7610000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2419                              <1> sndc8:
  2420 000056FC F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2421                              <1> sndc9:
  2422                              <1> 	; AL = Line status, AH = Modem status
  2423 000056FD C3                  <1> 	retn
  2424                              <1> 
  2425                              <1> get_cpos:
  2426                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2427                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2428                              <1> 	;
  2429                              <1> 	; INPUT -> bl = video page number
  2430                              <1> 	; RETURN -> dx = cursor position
  2431                              <1> 
  2432 000056FE 53                  <1> 	push	ebx
  2433 000056FF 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2434 00005702 D0E3                <1> 	shl	bl, 1
  2435 00005704 81C3[56610000]      <1> 	add	ebx, cursor_posn
  2436 0000570A 668B13              <1> 	mov	dx, [ebx]
  2437 0000570D 5B                  <1> 	pop	ebx
  2438 0000570E C3                  <1> 	retn
  2439                              <1> 
  2440                              <1> read_ac_current:
  2441                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2442                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2443                              <1> 	;
  2444                              <1> 	; INPUT -> bl = video page number
  2445                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2446                              <1> 
  2447 0000570F E807BDFFFF          <1> 	call 	find_position ; 'video.inc'
  2448                              <1> 	; dx = status port
  2449                              <1> 	; esi = cursor location/address
  2450 00005714 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2451 0000571A 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2452 0000571D C3                  <1> 	retn
  2453                              <1> 
  2454                              <1> syssleep:
  2455                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2456                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2457                              <1> 	;
  2458                              <1> 	; Retro UNIX 8086 v1 feature only
  2459                              <1> 	; (INPUT -> none)
  2460                              <1> 	;
  2461 0000571E 0FB61D[49650000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2462 00005725 8AA3[53620000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2463 0000572B E8E5EEFFFF          <1> 	call	sleep
  2464 00005730 E9CCD9FFFF          <1> 	jmp	sysret
  2465                              <1> 
  2466                              <1> 	; 27/02/2022
  2467                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2468                              <1> %if 0
  2469                              <1> 
  2470                              <1> vp_clr:
  2471                              <1> 	; Reset/Clear Video Page
  2472                              <1> 	;
  2473                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2474                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2475                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2476                              <1> 	;
  2477                              <1> 	; Retro UNIX 8086 v1 feature only !
  2478                              <1> 	;
  2479                              <1> 	; INPUTS -> 
  2480                              <1> 	;   BL = video page number	 
  2481                              <1> 	;
  2482                              <1> 	; OUTPUT ->
  2483                              <1> 	;   none
  2484                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2485                              <1> 	;
  2486                              <1> 	; 04/12/2013
  2487                              <1> 	sub	al, al
  2488                              <1> 	; al = 0 (clear video page)
  2489                              <1> 	; bl = video page
  2490                              <1> 	mov	ah, 07h
  2491                              <1> 	; ah = 7 (attribute/color)
  2492                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2493                              <1> 	; 24/12/2021
  2494                              <1> 	xor	ecx, ecx
  2495                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2496                              <1> 	call	scroll_up
  2497                              <1> 	; bl = video page
  2498                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2499                              <1> 	; 24/12/2021
  2500                              <1> 	xor	edx, edx 
  2501                              <1> 	jmp 	set_cpos
  2502                              <1> 
  2503                              <1> %endif
  2504                              <1> 
  2505                              <1> sysmsg:
  2506                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2507                              <1> 	; 11/11/2015
  2508                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2509                              <1> 	; Print user-application message on user's console tty
  2510                              <1> 	;
  2511                              <1> 	; Input -> EBX = Message address
  2512                              <1> 	;	   ECX = Message length (max. 255)
  2513                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2514                              <1> 	;
  2515 00005735 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2516                              <1> 	;ja	sysret ; nothing to do with big message size
  2517 0000573B 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2518 0000573D 08C9                <1> 	or	cl, cl
  2519                              <1> 	;jz	sysret
  2520 0000573F 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2521 00005741 20D2                <1> 	and	dl, dl
  2522 00005743 7502                <1> 	jnz	short sysmsg0
  2523 00005745 B207                <1> 	mov	dl, 07h ; default color
  2524                              <1> 		; (black background, light gray character)
  2525                              <1> sysmsg0:
  2526 00005747 891D[20650000]      <1> 	mov	[u.base], ebx
  2527 0000574D 8815[67610000]      <1> 	mov	[ccolor], dl ; color attributes
  2528 00005753 89E5                <1> 	mov	ebp, esp
  2529 00005755 31DB                <1> 	xor	ebx, ebx ; 0
  2530 00005757 891D[28650000]      <1> 	mov	[u.nread], ebx ; 0
  2531                              <1> 	;
  2532 0000575D 381D[61650000]      <1> 	cmp	[u.kcall], bl ; 0
  2533 00005763 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2534                              <1> 	;
  2535 00005765 890D[24650000]      <1> 	mov	[u.count], ecx
  2536 0000576B 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2537                              <1> 	; 24/12/2021
  2538                              <1> 	; (dword alignment for esp)
  2539 0000576C F6C103              <1> 	test	cl, 3
  2540 0000576F 7404                <1> 	jz	short sysmsg_7
  2541 00005771 80C903              <1> 	or	cl, 3
  2542 00005774 41                  <1> 	inc	ecx
  2543                              <1> sysmsg_7:
  2544 00005775 29CC                <1> 	sub	esp, ecx
  2545 00005777 89E7                <1> 	mov	edi, esp
  2546 00005779 89E6                <1> 	mov	esi, esp
  2547 0000577B 66891D[5F650000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2548                              <1> 	; 11/11/2015
  2549 00005782 8A25[30650000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2550                              <1> 	; 0 = none
  2551 00005788 FECC                <1> 	dec	ah
  2552 0000578A 790C                <1> 	jns	short sysmsg1 
  2553 0000578C 8A1D[49650000]      <1> 	mov	bl, [u.uno] ; process number	
  2554 00005792 8AA3[53620000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2555                              <1> sysmsg1:
  2556 00005798 8825[4E650000]      <1> 	mov	[u.ttyn], ah
  2557                              <1> sysmsg2:
  2558 0000579E E84BF6FFFF          <1> 	call	cpass
  2559 000057A3 7416                <1> 	jz	short sysmsg5
  2560 000057A5 AA                  <1> 	stosb
  2561 000057A6 20C0                <1> 	and	al, al
  2562 000057A8 75F4                <1> 	jnz	short sysmsg2
  2563                              <1> sysmsg3:
  2564 000057AA 80FC07              <1> 	cmp	ah, 7 ; tty number
  2565 000057AD 7711                <1> 	ja	short sysmsg6 ; serial port
  2566 000057AF E83E000000          <1> 	call	print_cmsg
  2567                              <1> sysmsg4:
  2568 000057B4 89EC                <1> 	mov	esp, ebp	
  2569                              <1> sysmsg8: ; 24/12/2021	
  2570 000057B6 E946D9FFFF          <1> 	jmp	sysret
  2571                              <1> sysmsg5:
  2572 000057BB C60700              <1> 	mov	byte [edi], 0
  2573 000057BE EBEA                <1> 	jmp	short sysmsg3
  2574                              <1> sysmsg6:
  2575 000057C0 8A06                <1> 	mov	al, [esi]
  2576 000057C2 E843FEFFFF          <1> 	call	sndc
  2577 000057C7 72EB                <1> 	jc	short sysmsg4
  2578 000057C9 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2579 000057CC 76E6                <1> 	jna	short sysmsg4
  2580 000057CE 46                  <1> 	inc 	esi
  2581 000057CF 8A25[4E650000]      <1> 	mov	ah, [u.ttyn]
  2582 000057D5 EBE9                <1> 	jmp	short sysmsg6
  2583                              <1> 
  2584                              <1> sysmsgk: ; Temporary (01/07/2015)
  2585                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2586                              <1> 	; (ECX -character count- will not be considered)
  2587 000057D7 8B35[20650000]      <1> 	mov	esi, [u.base]
  2588 000057DD 8A25[66610000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2589 000057E3 8825[4E650000]      <1> 	mov	[u.ttyn], ah
  2590 000057E9 C605[61650000]00    <1> 	mov	byte [u.kcall], 0
  2591 000057F0 EBB8                <1> 	jmp	short sysmsg3
  2592                              <1> 	
  2593                              <1> print_cmsg: 
  2594                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2595                              <1> 	;
  2596                              <1> 	; print message (on user's console tty) 
  2597                              <1> 	;	with requested color
  2598                              <1> 	;
  2599                              <1> 	; INPUTS:
  2600                              <1> 	;	esi = message address
  2601                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2602                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2603                              <1> 	;
  2604 000057F2 AC                  <1> 	lodsb
  2605                              <1> pcmsg1:
  2606 000057F3 56                  <1> 	push 	esi
  2607 000057F4 0FB61D[4E650000]    <1>         movzx   ebx, byte [u.ttyn]
  2608 000057FB 8A25[67610000]      <1> 	mov	ah, [ccolor]
  2609 00005801 E8AFBAFFFF          <1> 	call 	write_tty
  2610 00005806 5E                  <1> 	pop	esi
  2611 00005807 AC                  <1> 	lodsb
  2612 00005808 20C0                <1> 	and 	al, al  ; 0
  2613 0000580A 75E7                <1> 	jnz 	short pcmsg1
  2614 0000580C C3                  <1> 	retn
  2615                              <1> 
  2616                              <1> sysgeterr:
  2617                              <1> 	; 16/02/2022
  2618                              <1> 	; 09/12/2015
  2619                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2620                              <1> 	; Get last error number or page fault count
  2621                              <1> 	; (for debugging)
  2622                              <1> 	;
  2623                              <1> 	; Input -> EBX = return type
  2624                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2625                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2626                              <1> 	;	   FFFFFFFEh = total page fault count
  2627                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2628                              <1> 	;
  2629                              <1> 	; Output -> EAX = last error number or page fault count
  2630                              <1> 	;	   (depending on EBX input)
  2631                              <1> 	; 	
  2632 0000580D 21DB                <1> 	and 	ebx, ebx
  2633 0000580F 750F                <1> 	jnz	short glerr_2
  2634                              <1> glerr_0:
  2635 00005811 A1[4F650000]        <1> 	mov	eax, [u.error]
  2636                              <1> glerr_1:
  2637 00005816 A3[00650000]        <1> 	mov	[u.r0], eax
  2638                              <1>  	;retn
  2639                              <1> 	; 16/02/2022 (BugFix)
  2640 0000581B E9E1D8FFFF          <1> 	jmp	sysret
  2641                              <1> glerr_2:
  2642 00005820 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2643 00005821 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2644 00005823 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2645 00005824 75EB                <1> 	jnz	short glerr_0
  2646 00005826 A1[EC610000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2647 0000582B EBE9                <1>         jmp     short glerr_1
  2648                              <1> glerr_3:
  2649 0000582D A1[63650000]        <1> 	mov 	eax, [u.pfcount]
  2650 00005832 EBE2                <1> 	jmp	short glerr_1
  2651                              <1> 
  2652                              <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2653                              <1> ;	     - PRINTER BIOS (Functions)		
  2654                              <1> 
  2655                              <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 
  2656                              <1> ;
  2657                              <1> ;--- INT 17 H ------------------------------------------------------------------
  2658                              <1> ; PRINTER_IO								       :
  2659                              <1> ;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
  2660                              <1> ; INPUT 								       :
  2661                              <1> ;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
  2662                              <1> ;		    ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT)  :
  2663                              <1> ;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
  2664                              <1> ;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
  2665                              <1> ;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
  2666                              <1> ;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
  2667                              <1> ;		   7	   6	   5	   4	   3	   2-1	   0	       :
  2668                              <1> ;		   |	   |	   |	   |	   |	   |	   |_TIME OUT  :
  2669                              <1> ;		   |	   |	   |	   |	   |	   |		       :
  2670                              <1> ;		   |	   |	   |	   |	   |	   |_ UNUSED	       :
  2671                              <1> ;		   |	   |	   |	   |	   |			       :
  2672                              <1> ;		   |	   |	   |	   |	   |_ 1 = I/O ERROR	       :
  2673                              <1> ;		   |	   |	   |	   |				       :
  2674                              <1> ;		   |	   |	   |	   |_ 1 = SELECTED		       :
  2675                              <1> ;		   |	   |	   |					       :
  2676                              <1> ;		   |	   |	   |_ 1 = OUT OF PAPER			       :
  2677                              <1> ;		   |	   |						       :
  2678                              <1> ;		   |	   |_ 1 = ACKNOWLEDGE				       :
  2679                              <1> ;		   |							       :
  2680                              <1> ;		   |_ 1 = NOT BUSY					       :
  2681                              <1> ;									       :
  2682                              <1> ;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
  2683                              <1> ;		IN @PRINTER_BASE AREA					       :
  2684                              <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
  2685                              <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
  2686                              <1> ;									       :
  2687                              <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT	       :
  2688                              <1> ; TIME OUT WAITS. DEFAULT=20 * 4					       :
  2689                              <1> ;									       :
  2690                              <1> ; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
  2691                              <1> ;		ALL OTHERS UNCHANGED					       :
  2692                              <1> ;-------------------------------------------------------------------------------
  2693                              <1> 
  2694                              <1> int17h:
  2695                              <1> 	; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20)
  2696                              <1> 	; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985)
  2697                              <1> 	;
  2698                              <1> 	; (Default printer port: 378h) ; LPT1
  2699                              <1> 	; (Number of printers = 1)
  2700                              <1> 	
  2701                              <1> 	PRINTER_BASE equ 378h ; LPT1
  2702                              <1> 	;PRINT_TIM_OUT equ 4*80*65536 
  2703                              <1> 			; (Ref: IBM PC-AT BIOS v2 PRT.ASM)	 
  2704                              <1> 
  2705                              <1> 	PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY
  2706                              <1> 			; (Ref: AWARD BIOS 1999 ATORGS.ASM)		
  2707                              <1> 
  2708                              <1> 	; INPUT:
  2709                              <1> 	;	ah = 0 -> print the character in AL 
  2710                              <1> 	;		 (sys write with write count >0)
  2711                              <1> 	;	ah = 1 -> initialize printer port
  2712                              <1> 	;		 (sys open)	
  2713                              <1> 	;	ah = 2 -> read the printer status 
  2714                              <1> 	;		 (sys write with write count = 0)
  2715                              <1> 	; OUTPUT:
  2716                              <1> 	;	ah = printer status
  2717                              <1> 
  2718                              <1> 	; Modified registers: eax, ecx, edx
  2719                              <1> 
  2720                              <1> PRINTER_IO_1:
  2721 00005834 08E4                <1> 	or	ah, ah
  2722 00005836 7417                <1> 	jz	short _b20
  2723 00005838 FECC                <1> 	dec	ah
  2724 0000583A 7444                <1> 	jz	short _b80
  2725                              <1> 	;dec 	ah
  2726                              <1> 	;jz	short _b50
  2727                              <1> _b50:
  2728                              <1> 	;-----	PRINTER STATUS
  2729                              <1> B50:
  2730 0000583C 50                  <1> 	push	eax		; SAVE (AL) REGISTER
  2731                              <1> B60:
  2732 0000583D 66BA7903            <1> 	mov	dx, PRINTER_BASE+1
  2733                              <1> 				; GET PRINTER ATTACHMENT BASE ADDRESS
  2734                              <1> 				; POINT TO CONTROL PORT
  2735 00005841 EC                  <1> 	in	al, dx		; PRE-CHARGE +BUSY LINE IF FLOATING
  2736 00005842 EC                  <1> 	in	al, dx		; GET PRINTER STATUS HARDWARE BITS
  2737 00005843 88C4                <1> 	mov	ah, al		; SAVE
  2738 00005845 80E4F8              <1> 	and	ah, 0F8h	; TURN OFF UNUSED BITS
  2739                              <1> B70:
  2740 00005848 5A                  <1> 	pop	edx		; RECOVER (AL) REGISTER
  2741 00005849 88D0                <1> 	mov	al, dl		; MOVE CHARACTER INTO (AL)
  2742 0000584B 80F448              <1> 	xor	ah, 48h		; FLIP A COUPLE OF BITS
  2743                              <1> B10:
  2744 0000584E C3                  <1> 	retn			; RETURN FROM ROUTINE WITH STATUS IN AH
  2745                              <1> _b20:
  2746                              <1> 	;-----	PRINT THE CHARACTER IN (AL)
  2747 0000584F B9A08C0000          <1> 	mov	ecx, PRINT_TIM_OUT ; (1 second)
  2748                              <1> B20:
  2749 00005854 50                  <1> 	push	eax		; SAVE VALUE TO PRINT
  2750 00005855 66BA7803            <1> 	mov	dx, PRINTER_BASE
  2751 00005859 EE                  <1> 	out	dx, al		; OUTPUT CHARACTER TO DATA PORT
  2752 0000585A FEC2                <1> 	inc	dl		; POINT TO STATUS PORT
  2753                              <1> 
  2754                              <1> 	;-----	CHECK FOR PRINTER BUSY
  2755                              <1> B25:
  2756                              <1> 	;-----	WAIT BUSY
  2757                              <1> B35:
  2758 0000585C EC                  <1> 	in	al, dx		; GET STATUS
  2759 0000585D 88C4                <1> 	mov	ah, al		; STATUS TO (AH) ALSO
  2760 0000585F A880                <1> 	test	al, 80h		; IS THE PRINTER CURRENTLY BUSY? (*)
  2761 00005861 750F                <1> 	jnz	short B40	; GO TO OUTPUT STROBE
  2762 00005863 E831000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2763 00005868 E2F2                <1> 	loop	B35		; LOOP IF YES (*)
  2764                              <1> 
  2765 0000586A 80CC01              <1> 	or	ah, 1		; SET ERROR FLAG
  2766 0000586D 80E4F9              <1> 	and	ah, 0F9h	; TURN OFF THE UNUSED BITS
  2767 00005870 EBD6                <1> 	jmp	short B70	; RETURN WITH ERROR FLAG SET
  2768                              <1> 
  2769                              <1> B40:				; SEND STROBE PULSE
  2770 00005872 B00D                <1> 	mov	al, 0Dh		; SET THE STROBE LOW (BIT ON)
  2771 00005874 6642                <1> 	inc	dx		; OUTPUT STROBE TO CONTROL PORT
  2772 00005876 FA                  <1> 	cli			; PREVENT INTERRUPT PULSE STRETCHING
  2773 00005877 EE                  <1> 	out	dx, al		; OUTPUT STROBE BIT > 1us < 5us
  2774                              <1> 	; IODELAY
  2775                              <1> 	;jmp	short $+2	; I/O DELAY TO ALLOW FOR LINE LOADING
  2776                              <1> 	;jmp	short $+2	; AND FOR CORRECT PULSE WIDTH
  2777                              <1> 	; NEWIODELAY
  2778 00005878 E6EB                <1> 	out	0EBh, al
  2779                              <1> 
  2780 0000587A B00C                <1> 	mov	al, 0Ch		; SET THE -STROBE HIGH
  2781 0000587C EE                  <1> 	out	dx, al
  2782 0000587D FB                  <1> 	sti			; INTERRUPTS BACK ON
  2783                              <1> 	;pop	eax		; RECOVER THE OUTPUT CHAR
  2784                              <1> 	;jmp	short B50
  2785 0000587E EBBD                <1> 	jmp	short B60
  2786                              <1> 
  2787                              <1> _b80:
  2788                              <1> 	;-----	INITIALIZE THE PRINTER PORT
  2789                              <1> B80:
  2790 00005880 50                  <1> 	push	eax		; SAVE (AL)
  2791 00005881 66BA7A03            <1> 	mov	dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT
  2792 00005885 B008                <1> 	mov	al, 8		; SET INIT LINE LOW
  2793 00005887 EE                  <1> 	out	dx, al
  2794                              <1> 	;mov	eax, 1000*4	; ADJUST FOR INITIALIZATION DELAY LOOP
  2795 00005888 B989080000          <1> 	mov	ecx, WAIT_PRN_INIT ; (65536 micro seconds)
  2796                              <1> B90:				; INIT_LOOP
  2797                              <1> 	;dec	eax		; LOOP FOR RESET TO TAKE
  2798                              <1> 	;jnz	short B90	; INIT_LOOP
  2799 0000588D E807000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2800 00005892 E2F9                <1> 	loop	B90	
  2801 00005894 B00C                <1> 	mov	al, 0Ch		; NO INTERRUPTS, NON AUTO LF, INIT HIGH
  2802 00005896 EE                  <1> 	out	dx, al
  2803 00005897 EBA4                <1> 	jmp	short B60	; EXIT THROUGH STATUS ROUTINE
  2804                              <1> 
  2805                              <1> 
  2806                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2807                              <1> ; -------------------------------------------------------------------
  2808                              <1> ;
  2809                              <1> ;;Wait while printer initializes should be 65,536 microseconds.
  2810                              <1> ;;65536/30 = 2185
  2811                              <1> ;			PUBLIC	WAIT_PRN_INIT_LO
  2812                              <1> ;WAIT_PRN_INIT_LO	DW	2185
  2813                              <1> ;			PUBLIC	WAIT_PRN_INIT_HI
  2814                              <1> ;WAIT_PRN_INIT_HI	DW	0
  2815                              <1> ;
  2816                              <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022
  2817                              <1> ;
  2818                              <1> ;;Wait for printer not busy should be 1,080,000 microseconds.
  2819                              <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us.
  2820                              <1> ;;1,080,000 / 30 = 36,000
  2821                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_LO
  2822                              <1> ;WAIT_PRN_NBUSY_LO	DW	36000
  2823                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_HI
  2824                              <1> ;WAIT_PRN_NBUSY_HI	DB	0
  2825                              <1> ;
  2826                              <1> ;WAIT_PRN_NBUSY	equ 36000 ; 12/06/2022
  2827                              <1> 
  2828                              <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999)
  2829                              <1> ; ------------------------------------------
  2830                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2831                              <1> ;   	INPUT: BX:CX = number of refresh periods to wait
  2832                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2833                              <1> ;	OUTPUT: BX:CX destroyed.
  2834                              <1> ;
  2835                              <1> ;	SAVES:	AX (except when NO STACK)
  2836                              <1> ;
  2837                              <1> ;	NOTES:	This routine can be (and is) used with no stack. When
  2838                              <1> ;		used this way, AX is assumed to be destroyed.
  2839                              <1> 
  2840                              <1> WAIT_REFRESH:
  2841                              <1> 	; 13/06/2022
  2842                              <1> 	; Modified for Retro UNIX 386 v1
  2843                              <1> 	
  2844                              <1> 	; (wait for 30 micro seconds)
  2845                              <1> 
  2846                              <1> 	SYS1	equ 61h ; PORT_B
  2847                              <1> 
  2848                              <1> WR_SHORT:
  2849 00005899 50                  <1> 	push	eax
  2850                              <1> WR_STAT_0:
  2851 0000589A E461                <1> 	in	al, SYS1	; wait for high to low
  2852 0000589C A810                <1> 	test	al, 10h		; transition on memory
  2853 0000589E 75FA                <1> 	jnz	short WR_STAT_0 
  2854                              <1> WR_STAT_1:
  2855 000058A0 E461                <1> 	in	al, SYS1
  2856 000058A2 A810                <1> 	test	al, 10h
  2857 000058A4 74FA                <1> 	jz	short WR_STAT_1
  2858 000058A6 58                  <1> 	pop	eax
  2859 000058A7 C3                  <1> 	retn
  2061                                  
  2062                                  ; 07/03/2015
  2063                                  ; Temporary Code
  2064                                  display_disks:
  2065 000058A8 803D[5C5C0000]00        	cmp 	byte [fd0_type], 0
  2066 000058AF 7605                    	jna 	short ddsks1
  2067 000058B1 E87D000000              	call	pdskm
  2068                                  ddsks1:
  2069 000058B6 803D[5D5C0000]00        	cmp	byte [fd1_type], 0
  2070 000058BD 760C                    	jna	short ddsks2
  2071 000058BF C605[215E0000]31        	mov	byte [dskx], '1'
  2072 000058C6 E868000000              	call	pdskm
  2073                                  ddsks2:
  2074 000058CB 803D[5E5C0000]00        	cmp	byte [hd0_type], 0
  2075 000058D2 7654                    	jna	short ddsk6
  2076 000058D4 66C705[1F5E0000]68-     	mov	word [dsktype], 'hd'
  2076 000058DC 64                 
  2077 000058DD C605[215E0000]30        	mov	byte [dskx], '0'
  2078 000058E4 E84A000000              	call	pdskm
  2079                                  ddsks3:
  2080 000058E9 803D[5F5C0000]00        	cmp	byte [hd1_type], 0
  2081 000058F0 7636                    	jna	short ddsk6
  2082 000058F2 C605[215E0000]31        	mov	byte [dskx], '1'
  2083 000058F9 E835000000              	call	pdskm
  2084                                  ddsks4:
  2085 000058FE 803D[605C0000]00        	cmp	byte [hd2_type], 0
  2086 00005905 7621                    	jna	short ddsk6
  2087 00005907 C605[215E0000]32        	mov	byte [dskx], '2'
  2088 0000590E E820000000              	call	pdskm
  2089                                  ddsks5:
  2090 00005913 803D[615C0000]00        	cmp	byte [hd3_type], 0
  2091 0000591A 760C                    	jna	short ddsk6
  2092 0000591C C605[215E0000]33        	mov	byte [dskx], '3'
  2093 00005923 E80B000000              	call	pdskm
  2094                                  ddsk6:
  2095 00005928 BE[305E0000]            	mov	esi, nextline
  2096 0000592D E806000000              	call	pdskml
  2097                                  pdskm_ok:
  2098 00005932 C3                      	retn
  2099                                  pdskm:
  2100 00005933 BE[1D5E0000]            	mov	esi, dsk_ready_msg
  2101                                  pdskml:	
  2102 00005938 AC                      	lodsb
  2103 00005939 08C0                    	or	al, al
  2104 0000593B 74F5                    	jz	short pdskm_ok
  2105 0000593D 56                      	push	esi
  2106 0000593E 31DB                    	xor	ebx, ebx ; 0
  2107                                  			; Video page 0 (bl=0)
  2108 00005940 B407                    	mov	ah, 07h ; Black background, 
  2109                                  			; light gray forecolor
  2110 00005942 E86EB9FFFF              	call	write_tty
  2111 00005947 5E                      	pop	esi
  2112 00005948 EBEE                    	jmp	short pdskml
  2113                                  
  2114 0000594A 90<rep 6h>              align 16
  2115                                  
  2116                                  gdt:	; Global Descriptor Table
  2117                                  	; (30/07/2015, conforming cs)
  2118                                  	; (26/03/2015)
  2119                                  	; (24/03/2015, tss)
  2120                                  	; (19/03/2015)
  2121                                  	; (29/12/2013)
  2122                                  	;
  2123 00005950 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2124                                  	; 18/08/2014
  2125                                  			; 8h kernel code segment, base = 00000000h		
  2126 00005958 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2127                                  			; 10h kernel data segment, base = 00000000h	
  2128 00005960 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2129                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2130 00005968 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2131                                  			; 23h user data segment, base address = 400000h ; CORE
  2132 00005970 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2133                                  			; Task State Segment
  2134 00005978 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2135                                  			       ;  no IO permission in ring 3)
  2136                                  gdt_tss0:
  2137 0000597A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2138                                  gdt_tss1:
  2139 0000597C 00                      	db 0  ; TSS base address, bits 16-23 
  2140                                  	      		; 49h	
  2141 0000597D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2142 0000597E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2143                                  gdt_tss2:
  2144 0000597F 00                      	db 0  ; TSS base address, bits 24-31 
  2145                                  
  2146                                  gdt_end:
  2147                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2148                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2149                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2150                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2151                                  
  2152                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2153                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2154                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2155                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2156                                  		; W= Writeable, A= Accessed
  2157                                  	
  2158                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2159                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2160                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2161                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2162                                  
  2163                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2164                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2165                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2166                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2167                                  	
  2168                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2169                                  
  2170                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2171                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2172                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2173                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2174                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2175                                  		; AVL= Available to programmers	
  2176                                  
  2177                                  gdtd:
  2178 00005980 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2179 00005982 [50590000]                      dd gdt			; Address of the GDT
  2180                                  
  2181                                  	; 20/08/2014
  2182                                  idtd:
  2183 00005986 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2184 00005988 [D05E0000]                      dd idt			; Address of the IDT
  2185                                  
  2186                                  Align 4
  2187                                  
  2188                                  	; 21/08/2014
  2189                                  ilist:
  2190                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2191                                  	;
  2192                                  	; Exception list
  2193                                  	; 25/08/2014	
  2194 0000598C [1C080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2195 00005990 [23080000]              	dd	exc1	
  2196 00005994 [2A080000]              	dd 	exc2	
  2197 00005998 [31080000]              	dd	exc3	
  2198 0000599C [35080000]              	dd	exc4	
  2199 000059A0 [39080000]              	dd	exc5	
  2200 000059A4 [3D080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2201 000059A8 [41080000]              	dd	exc7	
  2202 000059AC [45080000]              	dd	exc8	
  2203 000059B0 [49080000]              	dd	exc9	
  2204 000059B4 [4D080000]              	dd 	exc10	
  2205 000059B8 [51080000]              	dd	exc11
  2206 000059BC [55080000]              	dd	exc12
  2207 000059C0 [59080000]              	dd	exc13	; 0Dh, General Protection Fault
  2208 000059C4 [5D080000]              	dd 	exc14	; 0Eh, Page Fault
  2209 000059C8 [61080000]              	dd	exc15
  2210 000059CC [65080000]              	dd	exc16
  2211 000059D0 [69080000]              	dd	exc17
  2212 000059D4 [6D080000]              	dd 	exc18
  2213 000059D8 [71080000]              	dd	exc19
  2214 000059DC [75080000]              	dd 	exc20
  2215 000059E0 [79080000]              	dd	exc21
  2216 000059E4 [7D080000]              	dd	exc22
  2217 000059E8 [81080000]              	dd	exc23
  2218 000059EC [85080000]              	dd 	exc24
  2219 000059F0 [89080000]              	dd	exc25
  2220 000059F4 [8D080000]              	dd	exc26
  2221 000059F8 [91080000]              	dd	exc27
  2222 000059FC [95080000]              	dd 	exc28
  2223 00005A00 [99080000]              	dd	exc29
  2224 00005A04 [9D080000]              	dd 	exc30
  2225 00005A08 [A1080000]              	dd	exc31
  2226                                  	; Interrupt list
  2227 00005A0C [58060000]              	dd	timer_int	; INT 20h
  2228                                  		;dd	irq0	
  2229 00005A10 [5D0B0000]              	dd	keyb_int	; 27/08/2014
  2230                                  		;dd	irq1
  2231 00005A14 [76070000]              	dd	irq2
  2232                                  		; COM2 int
  2233 00005A18 [7A070000]              	dd	irq3
  2234                                  		; COM1 int
  2235 00005A1C [85070000]              	dd	irq4
  2236 00005A20 [90070000]              	dd	irq5
  2237                                  ;DISKETTE_INT: ;06/02/2015
  2238 00005A24 [D01E0000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2239                                  		;dd	irq6
  2240                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2241                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2242 00005A28 [0C0B0000]              	dd	default_irq7	; 25/02/2015
  2243                                  		;dd	irq7
  2244                                  ; Real Time Clock Interrupt
  2245 00005A2C [AA090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2246                                  		;dd	irq8	; INT 28h
  2247 00005A30 [A0070000]              	dd	irq9
  2248 00005A34 [A4070000]              	dd	irq10
  2249 00005A38 [A8070000]              	dd	irq11
  2250 00005A3C [AC070000]              	dd	irq12
  2251 00005A40 [B0070000]              	dd	irq13
  2252                                  ;HDISK_INT1:  ;06/02/2015 	
  2253 00005A44 [9A230000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2254                                  		;dd	irq14
  2255                                  ;HDISK_INT2:  ;06/02/2015
  2256 00005A48 [BD230000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2257                                  		;dd	irq15	; INT 2Fh
  2258                                  		; 14/08/2015
  2259 00005A4C [E92F0000]              	dd	sysent		; INT 30h (system calls)
  2260                                  	
  2261                                  	;dd	ignore_int
  2262 00005A50 00000000                	dd	0
  2263                                  
  2264                                  ;;;
  2265                                  ;;; 11/03/2015
  2266                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2267                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - KYBDATA.INC
  2268                              <1> ; Last Modification: 13/06/2022
  2269                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2270                              <1> ;
  2271                              <1> ; ///////// KEYBOARD DATA ///////////////
  2272                              <1> 
  2273                              <1> ; 11/03/2015
  2274                              <1> ; 05/12/2014
  2275                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2276                              <1> ; 03/06/86  KEYBOARD BIOS
  2277                              <1> 
  2278                              <1> ;---------------------------------------------------------------------------------
  2279                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2280                              <1> ;---------------------------------------------------------------------------------
  2281                              <1> 
  2282                              <1> ;-----	TABLES FOR ALT CASE ------------
  2283                              <1> ;-----	ALT-INPUT-TABLE 
  2284 00005A54 524F50514B          <1> K30:	db	82,79,80,81,75
  2285 00005A59 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2286                              <1> ;-----	SUPER-SHIFT-TABLE 
  2287 00005A5E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2288 00005A64 161718191E1F        <1> 	db	22,23,24,25,30,31
  2289 00005A6A 202122232425        <1> 	db	32,33,34,35,36,37
  2290 00005A70 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2291 00005A76 3132                <1> 	db	49,50
  2292                              <1> 
  2293                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2294                              <1> ;-----	KEY_TABLE 
  2295 00005A78 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2296 00005A79 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2297 00005A7E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2298                              <1> _K6L    equ     $-_K6
  2299                              <1> 
  2300                              <1> ;-----	MASK_TABLE
  2301 00005A80 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2302 00005A81 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2303 00005A86 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2304                              <1> 
  2305                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2306 00005A88 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2307 00005A8E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2308                              <1> 	;db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2309 00005A94 FF7F94111705        <1> 	db	-1,127,148,17,23,5 ; 13/06/2022
  2310 00005A9A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2311 00005AA0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2312 00005AA6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2313 00005AAC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2314 00005AB2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2315 00005AB8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2316 00005ABE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2317                              <1> 	;				;----- FUNCTIONS ------		
  2318 00005AC2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2319 00005AC8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2320 00005ACE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2321 00005AD4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2322 00005ADA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2323                              <1> 
  2324                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2325 00005AE0 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2325 00005AE9 39302D3D0809        <1>
  2326 00005AEF 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2326 00005AF8 705B5D0DFF61736466- <1>
  2326 00005B01 67686A6B6C3B27      <1>
  2327 00005B08 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2327 00005B11 6D2C2E2FFF2AFF20FF  <1>
  2328                              <1> ;-----	LC TABLE SCAN
  2329 00005B1A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2330 00005B1F 4041424344          <1> 	db	64,65,66,67,68
  2331 00005B24 FFFF                <1> 	db	-1,-1			; NL, SL
  2332                              <1> 
  2333                              <1> ;-----	KEYPAD TABLE
  2334 00005B26 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2335 00005B2C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2336 00005B33 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2337                              <1> 
  2338                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2339 00005B38 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2339 00005B41 28295F2B0800        <1>
  2340 00005B47 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2340 00005B50 507B7D0DFF41534446- <1>
  2340 00005B59 47484A4B4C3A22      <1>
  2341 00005B60 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2341 00005B69 4D3C3E3FFF2AFF20FF  <1>
  2342                              <1> ;-----	UC TABLE SCAN
  2343 00005B72 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2344 00005B77 595A5B5C5D          <1> 	db	89,90,91,92,93
  2345 00005B7C FFFF                <1> 	db	-1,-1			; NL, SL
  2346                              <1> 
  2347                              <1> ;-----	NUM STATE TABLE
  2348 00005B7E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2348 00005B87 3233302E            <1>
  2349                              <1> 	;
  2350 00005B8B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2351                              <1> 
  2352                              <1> Align	4
  2353                              <1> ;----------------------------------------
  2354                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2355                              <1> ;----------------------------------------
  2356 00005B90 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2357 00005B91 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2358                              <1> 				; (29h default setting for video mode 3)
  2359                              <1> 				; Mode Select register Bits
  2360                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2361                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2362                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2363                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2364                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2365                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2366                              <1> 				;   BIT 6, 7 - Not Used
  2367                              <1> 
  2368                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2369                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2370                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2371                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2372                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2373                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2374                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2375                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2376                              <1> ; Mode & 37h = Video signal OFF
  2377                              <1> 			
  2378                              <1> 
  2379                              <1> ; 26/08/2014
  2380                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2381                              <1> ; Derived from IBM "pc-at" 
  2382                              <1> ; rombios source code (06/10/1985)
  2383                              <1> ; 'dseg.inc'
  2384                              <1> 
  2385                              <1> ;---------------------------------------;
  2386                              <1> ;	SYSTEM DATA AREA		;
  2387                              <1> ;----------------------------------------
  2388 00005B92 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2389                              <1> 
  2390                              <1> ;----------------------------------------
  2391                              <1> ;	KEYBOARD DATA AREAS		;
  2392                              <1> ;----------------------------------------
  2393                              <1> 
  2394 00005B93 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2395 00005B94 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2396 00005B95 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2397 00005B96 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2398 00005B97 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2399 00005B98 [A85B0000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2400 00005B9C [C85B0000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2401 00005BA0 [A85B0000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2402 00005BA4 [A85B0000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2403                              <1> ; ------  HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY
  2404 00005BA8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2405                              <1> 
  2406                              <1> ; /// End Of KEYBOARD DATA ///
  2267                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2268                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2269                              <1> ; Last Modification: 11/03/2015
  2270                              <1> ;		    (Data section for 'VIDEO.INC')	
  2271                              <1> ;
  2272                              <1> ; ///////// VIDEO DATA ///////////////
  2273                              <1> 
  2274                              <1> video_params:
  2275                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2276                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2277                              <1> 	; VIDEO MODE 3
  2278 00005BC8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2279 00005BCF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2280 00005BD4 00000000            <1> 	db	0,0,0,0
  2281                              <1> 
  2282                              <1> ; /// End Of VIDEO DATA ///
  2268                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2269                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKDATA.INC
  2270                              <1> ; Last Modification: 12/07/2022
  2271                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2272                              <1> ;
  2273                              <1> ; *****************************************************************************
  2274                              <1> ; Ref: Retro UNIX 386 v1.1 'diskdata.inc' modification: 11/07/2022
  2275                              <1> 
  2276                              <1> ;----------------------------------------
  2277                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2278                              <1> ;	REFERENCED BY POST & BIOS	:
  2279                              <1> ;----------------------------------------
  2280                              <1> 
  2281 00005BD8 [3B5C0000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2282                              <1> 
  2283                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2284                              <1> ;----------------------------------------------------------------
  2285                              <1> ; DISK_BASE							:
  2286                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2287                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2288                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2289                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2290                              <1> ;----------------------------------------------------------------
  2291                              <1> 
  2292                              <1> ;DISK_BASE:	
  2293                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2294                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2295                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2296                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2297                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2298                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2299                              <1> ;	DB	01BH		; GAP LENGTH
  2300                              <1> ;	DB	0FFH		; DTL
  2301                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2302                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2303                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2304                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2305                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2306                              <1> 
  2307                              <1> ;----------------------------------------
  2308                              <1> ;	ROM BIOS DATA AREAS		:
  2309                              <1> ;----------------------------------------
  2310                              <1> 
  2311                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2312                              <1> 
  2313                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2314                              <1> 
  2315                              <1> ;----------------------------------------
  2316                              <1> ;	DISKETTE DATA AREAS		:
  2317                              <1> ;----------------------------------------
  2318                              <1> 
  2319                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2320                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2321                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2322                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2323                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2324                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2325                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2326                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2327                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2328                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2329                              <1> 
  2330                              <1> ;----------------------------------------
  2331                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2332                              <1> ;----------------------------------------
  2333                              <1> 
  2334                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2335                              <1> 
  2336                              <1> ;----------------------------------------
  2337                              <1> ;	TIMER DATA AREA 		:
  2338                              <1> ;----------------------------------------
  2339                              <1> 
  2340                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2341                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2342                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2343                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2344                              <1> 
  2345                              <1> ;----------------------------------------
  2346                              <1> ;	ADDITIONAL MEDIA DATA		:
  2347                              <1> ;----------------------------------------
  2348                              <1> 
  2349                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2350                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2351                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2352                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2353                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2354                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2355                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2356                              <1> 
  2357                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2358                              <1> 
  2359                              <1> ;--------------------------------------------------------
  2360                              <1> ;	DRIVE TYPE TABLE				:
  2361                              <1> ;--------------------------------------------------------
  2362                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2363                              <1> DR_TYPE:
  2364 00005BDC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2365                              <1>                 ;DW      MD_TBL1
  2366 00005BDD [FA5B0000]          <1> 		dd	MD_TBL1
  2367 00005BE1 82                  <1> 		DB	02+BIT7ON
  2368                              <1> 		;DW      MD_TBL2
  2369 00005BE2 [075C0000]          <1>                 dd      MD_TBL2
  2370 00005BE6 02                  <1> DR_DEFAULT:	DB	02
  2371                              <1>                 ;DW      MD_TBL3
  2372 00005BE7 [145C0000]          <1> 		dd      MD_TBL3
  2373 00005BEB 03                  <1> 		DB	03
  2374                              <1>                 ;DW      MD_TBL4
  2375 00005BEC [215C0000]          <1> 		dd      MD_TBL4
  2376 00005BF0 84                  <1> 		DB	04+BIT7ON
  2377                              <1>                 ;DW      MD_TBL5
  2378 00005BF1 [2E5C0000]          <1> 		dd      MD_TBL5
  2379 00005BF5 04                  <1> 		DB	04
  2380                              <1>                 ;DW      MD_TBL6
  2381 00005BF6 [3B5C0000]          <1> 		dd      MD_TBL6
  2382                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2383                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2384                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2385                              <1> ;--------------------------------------------------------
  2386                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2387                              <1> ;--------------------------------------------------------
  2388                              <1> ;--------------------------------------------------------
  2389                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2390                              <1> ;--------------------------------------------------------
  2391                              <1> MD_TBL1:        
  2392 00005BFA DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2393 00005BFB 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2394 00005BFC 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2395 00005BFD 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2396 00005BFE 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2397 00005BFF 2A                  <1> 	DB	02AH		; GAP LENGTH
  2398 00005C00 FF                  <1> 	DB	0FFH		; DTL
  2399 00005C01 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2400 00005C02 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2401 00005C03 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2402 00005C04 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2403 00005C05 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2404 00005C06 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2405                              <1> ;--------------------------------------------------------
  2406                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2407                              <1> ;--------------------------------------------------------
  2408                              <1> MD_TBL2:        
  2409 00005C07 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2410 00005C08 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2411 00005C09 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2412 00005C0A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2413 00005C0B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2414 00005C0C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2415 00005C0D FF                  <1> 	DB	0FFH		; DTL
  2416 00005C0E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2417 00005C0F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2418 00005C10 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2419 00005C11 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2420 00005C12 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2421 00005C13 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2422                              <1> ;--------------------------------------------------------
  2423                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2424                              <1> ;--------------------------------------------------------
  2425                              <1> MD_TBL3:
  2426 00005C14 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2427 00005C15 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2428 00005C16 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2429 00005C17 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2430 00005C18 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2431 00005C19 1B                  <1> 	DB	01BH		; GAP LENGTH
  2432 00005C1A FF                  <1> 	DB	0FFH		; DTL
  2433 00005C1B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2434 00005C1C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2435 00005C1D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2436 00005C1E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2437 00005C1F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2438 00005C20 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2439                              <1> ;--------------------------------------------------------
  2440                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2441                              <1> ;--------------------------------------------------------
  2442                              <1> MD_TBL4:
  2443 00005C21 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2444 00005C22 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2445 00005C23 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2446 00005C24 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2447 00005C25 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2448 00005C26 2A                  <1> 	DB	02AH		; GAP LENGTH
  2449 00005C27 FF                  <1> 	DB	0FFH		; DTL
  2450 00005C28 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2451 00005C29 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2452 00005C2A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2453 00005C2B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2454 00005C2C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2455 00005C2D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2456                              <1> ;--------------------------------------------------------
  2457                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2458                              <1> ;--------------------------------------------------------
  2459                              <1> MD_TBL5:
  2460 00005C2E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2461 00005C2F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2462 00005C30 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2463 00005C31 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2464 00005C32 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2465 00005C33 2A                  <1> 	DB	02AH		; GAP LENGTH
  2466 00005C34 FF                  <1> 	DB	0FFH		; DTL
  2467 00005C35 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2468 00005C36 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2469 00005C37 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2470 00005C38 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2471 00005C39 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2472 00005C3A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2473                              <1> ;--------------------------------------------------------
  2474                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2475                              <1> ;--------------------------------------------------------
  2476                              <1> MD_TBL6:
  2477 00005C3B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2478 00005C3C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2479 00005C3D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2480 00005C3E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2481 00005C3F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2482 00005C40 1B                  <1> 	DB	01BH		; GAP LENGTH
  2483 00005C41 FF                  <1> 	DB	0FFH		; DTL
  2484 00005C42 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2485 00005C43 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2486 00005C44 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2487 00005C45 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2488 00005C46 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2489 00005C47 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2490                              <1> 
  2491                              <1> 
  2492                              <1> ; << diskette.inc >>
  2493                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2494                              <1> ;
  2495                              <1> ;----------------------------------------
  2496                              <1> ;	ROM BIOS DATA AREAS		:
  2497                              <1> ;----------------------------------------
  2498                              <1> 
  2499                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2500                              <1> 
  2501                              <1> ;----------------------------------------
  2502                              <1> ;	FIXED DISK DATA AREAS		:
  2503                              <1> ;----------------------------------------
  2504                              <1> 
  2505                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2506                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2507                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2508                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2509                              <1> 
  2510                              <1> ;----------------------------------------
  2511                              <1> ;	ADDITIONAL MEDIA DATA		:
  2512                              <1> ;----------------------------------------
  2513                              <1> 
  2514                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2515                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2516                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2517                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2518                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2519                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2520                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2521                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2522                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2523                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2524                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2525                              <1> 
  2526                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2527                              <1> ;
  2528                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2529                              <1> 
  2530                              <1> ERR_TBL:
  2531 00005C48 E0                  <1> 	db	NO_ERR
  2532 00005C49 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2533 00005C4D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2534                              <1> 
  2535                              <1> ; 11/07/2022
  2536                              <1> ; 17/12/2014 (mov ax, [cfd])
  2537                              <1> ; 11/12/2014
  2538                              <1> ;cfd:		db 0			; current floppy drive (for GET_PARM)
  2539                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2540                              <1> ;pfd:		db 1			; previous floppy drive (for GET_PARM)
  2541                              <1> 					; (initial value of 'pfd 
  2542                              <1> 					; must be different then 'cfd' value
  2543                              <1> 					; to force updating/initializing
  2544                              <1> 					; current drive parameters) 
  2545                              <1> 
  2546                              <1> ;; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2547 00005C51 FF                  <1> pfd:		db 0FFh
  2548                              <1> 
  2549                              <1> align 2
  2550                              <1> 
  2551 00005C52 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2552                              <1> 			      ; (170h)
  2553 00005C54 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2554                              <1> 
  2555                              <1> ; 05/01/2015 
  2556 00005C56 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2557                              <1> 
  2558                              <1> ; *****************************************************************************
  2269                                  ;;;
  2270                                  
  2271 00005C57 90                      Align 2
  2272                                  
  2273                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2274 00005C58 00                      boot_drv:    db 0 ; boot drive number (physical)
  2275                                  ; 24/11/2014
  2276 00005C59 00                      drv:	     db 0 
  2277 00005C5A 00                      last_drv:    db 0 ; last hdd
  2278 00005C5B 00                      hdc:         db 0  ; number of hard disk drives
  2279                                  		     ; (present/detected)
  2280                                  ;
  2281                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2282                                  ; Physical drive type & flags
  2283 00005C5C 00                      fd0_type:    db 0  ; floppy drive type
  2284 00005C5D 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2285                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2286                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2287                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2288                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2289 00005C5E 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2290 00005C5F 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2291 00005C60 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2292 00005C61 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2293                                  		     ; bit 0 - Fixed disk access subset supported
  2294                                  		     ; bit 1 - Drive locking and ejecting
  2295                                  		     ; bit 2 - Enhanced disk drive support
  2296                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2297                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2298                                  		     ; will interpret it as 'LBA ready'!)		
  2299                                  
  2300                                  ; 12/07/2022
  2301                                  ; (drv.cylinders, drv.spt, drv.spt will not be used now on)
  2302                                  ; ('diskio.inc')
  2303                                  ; ((spt and heads and cylinder counts will be taken from DPT))
  2304                                  
  2305                                  ; 11/03/2015 - 10/07/2015
  2306                                  ;drv.cylinders: dw 0,0,0,0,0,0,0
  2307                                  ;drv.heads:     dw 0,0,0,0,0,0,0
  2308                                  ;drv.spt:       dw 0,0,0,0,0,0,0
  2309                                  ; 12/07/2022 - 11/03/2015
  2310 00005C62 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2310 00005C6B 000000000000000000-
  2310 00005C74 000000000000000000-
  2310 00005C7D 00                 
  2311 00005C7E 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2312 00005C85 00000000000000          drv.error:     db 0,0,0,0,0,0,0
  2313                                  ;
  2314                                  
  2315                                  ; 27/08/2014
  2316                                  scr_row:
  2317 00005C8C E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2318                                  scr_col:
  2319 00005C90 00000000                	dd 0
  2320                                  
  2321                                  ;; 14/08/2015
  2322                                  ;;msgPM:
  2323                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2324                                  msgKVER:
  2325                                  	;;;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.17 [04/02/2016]", 0
  2326                                  	;;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.18 [29/04/2022]", 0	
  2327                                  	;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.19 [02/06/2022]", 0
  2328                                  	;;db "Retro UNIX 386 v1 - Kernel v0.2.0.20 [14/06/2022]", 0
  2329                                  	;db "Retro UNIX 386 v1 - Kernel v0.2.0.21 [12/07/2022]", 0
  2330 00005C94 526574726F20554E49-     	db "Retro UNIX 386 v1 - Kernel v0.2.0.22 [24/07/2022]", 0
  2330 00005C9D 582033383620763120-
  2330 00005CA6 2D204B65726E656C20-
  2330 00005CAF 76302E322E302E3232-
  2330 00005CB8 205B32342F30372F32-
  2330 00005CC1 3032325D00         
  2331                                  
  2332                                  Align 2
  2333                                  
  2334                                  ; 20/08/2014
  2335                                    ; /* This is the default interrupt "handler" :-) */ 
  2336                                    ; Linux v0.12 (head.s)
  2337                                  int_msg:
  2338 00005CC6 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2338 00005CCF 6E7465727275707420-
  2338 00005CD8 212000             
  2339                                  
  2340 00005CDB 90                      Align 2  
  2341                                  
  2342                                  ; 21/08/2014
  2343                                  timer_msg:
  2344 00005CDC 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2344 00005CE5 542032306829202120-
  2344 00005CEE 54696D657220496E74-
  2344 00005CF7 657272757074203A20 
  2345                                  tcountstr:
  2346 00005D00 303030303020            	db "00000 "
  2347 00005D06 00                      	db 0
  2348                                  
  2349 00005D07 90                      Align 2
  2350                                  	; 21/08/2014
  2351                                  exc_msg:
  2352 00005D08 435055206578636570-     	db "CPU exception ! "
  2352 00005D11 74696F6E202120     
  2353                                  excnstr: 		; 25/08/2014
  2354 00005D18 3F3F68202045495020-     	db "??h", "  EIP : "
  2354 00005D21 3A20               
  2355                                  EIPstr: ; 29/08/2014
  2356 00005D23 00<rep Ch>              	times 12 db 0
  2357                                  rtc_msg:
  2358 00005D2F 5265616C2054696D65-     	db "Real Time Clock - "
  2358 00005D38 20436C6F636B202D20 
  2359                                  datestr:
  2360 00005D41 30302F30302F303030-     	db "00/00/0000"
  2360 00005D4A 30                 
  2361 00005D4B 20                      	db " "
  2362                                  daystr:
  2363 00005D4C 44415920                	db "DAY "
  2364                                  timestr:	
  2365 00005D50 30303A30303A3030                db "00:00:00"
  2366 00005D58 20                      	db " "
  2367 00005D59 00                      	db 0 
  2368                                  
  2369                                  daytmp:
  2370                                  	; 28/02/2015
  2371 00005D5A 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2371 00005D63 4F4E20545545205745-
  2371 00005D6C 442054485520465249-
  2371 00005D75 2053415420         
  2372                                  
  2373 00005D7A FF                      ptime_seconds: db 0FFh
  2374                                  
  2375                                  	; 23/02/2015
  2376                                  	; 25/08/2014
  2377                                  ;scounter:
  2378                                  ;	db 5
  2379                                  ;	db 19
  2380                                  
  2381                                  ;; 05/11/2014
  2382                                  ;msg_out_of_memory:
  2383                                  ;	db 	07h, 0Dh, 0Ah
  2384                                  ;	db      'Insufficient memory ! '
  2385                                  ;	db	'(Minimum 2 MB memory is needed.)'
  2386                                  ; 	db	0Dh, 0Ah, 0
  2387                                  	;
  2388                                  setup_error_msg:
  2389 00005D7B 0D0A                    	db 0Dh, 0Ah
  2390 00005D7D 4469736B2053657475-     	db 'Disk Setup Error!' 
  2390 00005D86 70204572726F7221   
  2391 00005D8E 0D0A00                  	db 0Dh, 0Ah,0
  2392                                  
  2393                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2394                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2395                                  ;	  db 0 ; upper left row (for scroll)	
  2396                                  
  2397                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2398                                  ;	  db 24 ; lower right row (for scroll)
  2399                                  
  2400                                  
  2401                                  ; 06/11/2014 (Temporary Data)
  2402                                  ; Memory Information message
  2403                                  ; 14/08/2015
  2404                                  msg_memory_info:
  2405 00005D91 07                      	db	07h
  2406 00005D92 0D0A                    	db	0Dh, 0Ah
  2407                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2408 00005D94 546F74616C206D656D-     	db	"Total memory : "
  2408 00005D9D 6F7279203A20       
  2409                                  mem_total_b_str: ; 10 digits
  2410 00005DA3 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2410 00005DAC 302062797465730D0A 
  2411 00005DB5 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2411 00005DBE 202020202020202020 
  2412                                  mem_total_p_str: ; 7 digits
  2413 00005DC7 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2413 00005DD0 616765730D0A       
  2414 00005DD6 0D0A                    	db 	0Dh, 0Ah
  2415 00005DD8 46726565206D656D6F-     	db	"Free memory  : "
  2415 00005DE1 727920203A20       
  2416                                  free_mem_b_str:  ; 10 digits
  2417 00005DE7 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2417 00005DF0 3F2062797465730D0A 
  2418 00005DF9 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2418 00005E02 202020202020202020 
  2419                                  free_mem_p_str:  ; 7 digits
  2420 00005E0B 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2420 00005E14 616765730D0A       
  2421 00005E1A 0D0A00                  	db	0Dh, 0Ah, 0
  2422                                  
  2423                                  dsk_ready_msg:
  2424 00005E1D 0D0A                    	db 	0Dh, 0Ah
  2425                                  dsktype:
  2426 00005E1F 6664                    	db	'fd'
  2427                                  dskx:
  2428 00005E21 30                      	db	'0'
  2429 00005E22 20                      	db	20h
  2430 00005E23 697320524541445920-     	db 	'is READY ...'
  2430 00005E2C 2E2E2E             
  2431 00005E2F 00                      	db 	0
  2432                                  nextline:
  2433 00005E30 0D0A00                  	db 	0Dh, 0Ah, 0
  2434                                  
  2435                                  ; KERNEL - SYSINIT Messages
  2436                                  ; 24/08/2015
  2437                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2438                                  ; 14/07/2013
  2439                                  ;kernel_init_err_msg:
  2440                                  ;	db 0Dh, 0Ah
  2441                                  ;	db 07h
  2442                                  ;	db 'Kernel initialization ERROR !'
  2443                                  ;	db 0Dh, 0Ah, 0 
  2444                                  ; 24/08/2015
  2445                                  ;;; (temporary kernel init message has been removed
  2446                                  ;;;  from 'sys_init' code)
  2447                                  ;kernel_init_ok_msg: 
  2448                                  ;	db 0Dh, 0Ah
  2449                                  ;	db 07h
  2450                                  ;	db 'Welcome to Retro UNIX 386 v1 Operating System !'
  2451                                  ;	db 0Dh, 0Ah
  2452                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.0.17)'
  2453                                  ;	db 0Dh, 0Ah, 0
  2454                                  panic_msg:
  2455 00005E33 0D0A07                  	db 0Dh, 0Ah, 07h
  2456 00005E36 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2456 00005E3F 726E656C2050616E69-
  2456 00005E48 632021             
  2457 00005E4B 0D0A00                  	db 0Dh, 0Ah, 0
  2458                                  etc_init_err_msg:
  2459 00005E4E 0D0A                    	db 0Dh, 0Ah
  2460 00005E50 07                      	db 07h
  2461 00005E51 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2461 00005E5A 74632F696E69742021-
  2461 00005E63 3F                 
  2462 00005E64 0D0A00                  	db 0Dh, 0Ah, 0
  2463                                  
  2464                                  ; 10/05/2015
  2465                                  badsys_msg:
  2466 00005E67 0D0A                    	db 0Dh, 0Ah
  2467 00005E69 07                      	db 07h
  2468 00005E6A 496E76616C69642053-     	db 'Invalid System Call !'
  2468 00005E73 797374656D2043616C-
  2468 00005E7C 6C2021             
  2469 00005E7F 0D0A                    	db 0Dh, 0Ah
  2470 00005E81 4541583A20              	db 'EAX: '
  2471                                  bsys_msg_eax:
  2472 00005E86 303030303030303068      	db '00000000h'
  2473 00005E8F 0D0A                    	db 0Dh, 0Ah
  2474 00005E91 4549503A20              	db 'EIP: '
  2475                                  bsys_msg_eip:
  2476 00005E96 303030303030303068      	db '00000000h' 
  2477 00005E9F 0D0A00                  	db 0Dh, 0Ah, 0
  2478                                  
  2479                                  BSYS_M_SIZE equ $ - badsys_msg
  2480                                  
  2481                                  
  2482                                  align 2
  2483                                  
  2484                                  ; EPOCH Variables
  2485                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2486                                  ; 09/04/2013 epoch variables
  2487                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2488                                  ;
  2489 00005EA2 B207                    year: 	dw 1970
  2490                                  ;month: dw 1
  2491                                  ;day: 	dw 1
  2492                                  ;hour: 	dw 0
  2493                                  ;minute: dw 0
  2494                                  ;second: dw 0
  2495                                  ; 02/06/2022
  2496 00005EA4 01                      month:	db 1
  2497 00005EA5 01                      day:	db 1
  2498 00005EA6 01                      hour:	db 1
  2499 00005EA7 01                      minute: db 1
  2500 00005EA8 01                      second:	db 1
  2501 00005EA9 01                      	db 1
  2502                                  
  2503                                  DMonth:
  2504 00005EAA 0000                    	dw 0
  2505 00005EAC 1F00                    	dw 31
  2506 00005EAE 3B00                    	dw 59
  2507 00005EB0 5A00                    	dw 90
  2508 00005EB2 7800                    	dw 120
  2509 00005EB4 9700                    	dw 151
  2510 00005EB6 B500                    	dw 181
  2511 00005EB8 D400                    	dw 212
  2512 00005EBA F300                    	dw 243
  2513 00005EBC 1101                    	dw 273
  2514 00005EBE 3001                    	dw 304
  2515 00005EC0 4E01                    	dw 334
  2516                                  
  2517                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2518 00005EC2 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2519                                                       ; 1 and 16 MB, max. 3C00h = 15 MB.
  2520 00005EC4 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2521                                  		   ;   between 16 MB and 4 GB.
  2522                                  
  2523 00005EC6 90<rep Ah>              align 16
  2524                                  
  2525                                  bss_start:
  2526                                  
  2527                                  ABSOLUTE bss_start
  2528                                  
  2529                                  	; 11/03/2015
  2530                                  	; Interrupt Descriptor Table (20/08/2014)
  2531                                  idt:
  2532 00005ED0 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2533                                  idt_end:
  2534                                  
  2535                                  ;alignb 4
  2536                                  
  2537                                  task_state_segment:
  2538                                  	; 24/03/2015
  2539 000060D0 ????                    tss.link:   resw 1
  2540 000060D2 ????                    	    resw 1
  2541                                  ; tss offset 4	
  2542 000060D4 ????????                tss.esp0:   resd 1
  2543 000060D8 ????                    tss.ss0:    resw 1
  2544 000060DA ????                    	    resw 1	
  2545 000060DC ????????                tss.esp1:   resd 1
  2546 000060E0 ????                    tss.ss1:    resw 1
  2547 000060E2 ????                    	    resw 1 	
  2548 000060E4 ????????                tss.esp2:   resd 1
  2549 000060E8 ????                    tss.ss2:    resw 1
  2550 000060EA ????                    	    resw 1
  2551                                  ; tss offset 28
  2552 000060EC ????????                tss.CR3:    resd 1
  2553 000060F0 ????????                tss.eip:    resd 1
  2554 000060F4 ????????                tss.eflags: resd 1
  2555                                  ; tss offset 40
  2556 000060F8 ????????                tss.eax:    resd 1		 		
  2557 000060FC ????????                tss.ecx:    resd 1
  2558 00006100 ????????                tss.edx:    resd 1
  2559 00006104 ????????                tss.ebx:    resd 1
  2560 00006108 ????????                tss.esp:    resd 1
  2561 0000610C ????????                tss.ebp:    resd 1
  2562 00006110 ????????                tss.esi:    resd 1
  2563 00006114 ????????                tss.edi:    resd 1
  2564                                  ; tss offset 72
  2565 00006118 ????                    tss.ES:     resw 1
  2566 0000611A ????                    	    resw 1	
  2567 0000611C ????                    tss.CS:	    resw 1
  2568 0000611E ????                    	    resw 1
  2569 00006120 ????                    tss.SS:	    resw 1
  2570 00006122 ????                    	    resw 1
  2571 00006124 ????                    tss.DS:	    resw 1
  2572 00006126 ????                    	    resw 1
  2573 00006128 ????                    tss.FS:	    resw 1
  2574 0000612A ????                    	    resw 1
  2575 0000612C ????                    tss.GS:	    resw 1
  2576 0000612E ????                    	    resw 1		
  2577 00006130 ????                    tss.LDTR:   resw 1
  2578 00006132 ????                    	    resw 1
  2579                                  ; tss offset 100		
  2580 00006134 ????                    	    resw 1		
  2581 00006136 ????                    tss.IOPB:   resw 1
  2582                                  ; tss offset 104 
  2583                                  tss_end:
  2584                                  
  2585 00006138 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2586                                  		    ; (Physical address = Virtual address)	 	
  2587 0000613C ????????                memory_size: resd 1 ; memory size in pages
  2588 00006140 ????????                free_pages:  resd 1 ; number of free pages		
  2589 00006144 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2590                                  		    ; first free page search
  2591 00006148 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2592                                  		    ; next free page search will be
  2593                                  		    ; stopped after it. (end of M.A.T.)
  2594 0000614C ????????                first_page:  resd 1 ; offset value in M.A.T. which
  2595                                  		    ; first free page search
  2596                                  		    ; will be started on it. (for user)
  2597 00006150 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2598                                  
  2599                                  ;;;
  2600                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2601                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2602 00006154 ????                    CRT_START:   resw 1 ; starting address in regen buffer
  2603                                  		    ; NOTE: active page only
  2604 00006156 <res 10h>               cursor_posn: resw 8 ; cursor positions for video pages
  2605                                  active_page: 
  2606 00006166 ??                      ptty: 	     resb 1 ; current tty
  2607                                  ; 01/07/2015
  2608 00006167 ??                      ccolor:	     resb 1 ; current color attributes ('sysmsg')	
  2609                                  ; 26/10/2015
  2610                                  ; 07/09/2014
  2611 00006168 <res 14h>               ttychr:      resw ntty+2 ; Character buffer (multiscreen)
  2612                                  
  2613                                  ; 21/08/2014
  2614 0000617C ????????                tcount:	     resd 1
  2615                                  
  2616                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2617 00006180 ????????                p_time:      resd 1 ; present time (for systime & sysmdate)
  2618                                  
  2619                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2620                                  ; (open mode locks for pseudo TTYs)
  2621                                  ; [ major tty locks (return error in any conflicts) ]
  2622 00006184 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2623                                  
  2624                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2625                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2626 00006198 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2627                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2628                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2629                                  ;; 0 means serial port is not available 
  2630                                  ;;comprm: ; 25/06/2014
  2631 000061A2 ??                      com1p:       resb 1 ;;0E3h
  2632 000061A3 ??                      com2p:       resb 1 ;;0E3h
  2633                                  
  2634                                  ; 17/11/2015
  2635                                  ; request for response (from the terminal)	
  2636 000061A4 ????                    req_resp:     resw 1 			
  2637                                  ; 07/11/2015
  2638 000061A6 ??                      ccomport:    resb 1 ; current COM (serial) port
  2639                                  		    ; (0= COM1, 1= COM2)
  2640                                  ; 09/11/2015
  2641 000061A7 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2642                                  ; 07/11/2015
  2643 000061A8 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2644 000061AA ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2645                                  
  2646                                  ; 23/10/2015
  2647                                  ; SERIAL PORTS - COMMUNICATION MODES
  2648                                  ; (Retro UNIX 386 v1 feature only!)
  2649                                  ; 0 - command mode (default/initial mode)
  2650                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2651                                  ;;; communication modes for future versions:  
  2652                                  ; // 2 - keyboard mode (ascii+scancode input)
  2653                                  ; // 3 - mouse mode
  2654                                  ; // 4 - device control (output) mode
  2655                                  ; VALID COMMANDS for current version:
  2656                                  ; 	'LOGIN'
  2657                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2658                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2659                                  ;  Login response: db 0FFh, 'login', 0
  2660                                  ;	 ("login request accepted, wait for login prompt") 
  2661                                  ; When a login requests is received and acknowledged (by
  2662                                  ; serial port interrupt handler (communication procedure),
  2663                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2664                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2665                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2666                                  ; 
  2667                                  ; 'sys connect' system call is used to change communication mode
  2668                                  ; except 'LOGIN' command which is used to start terminal mode
  2669                                  ; by using (COM port) terminal.
  2670                                  
  2671                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2672                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2673                                  ;com1mode:    resb 1 ; communication mode for COM1
  2674                                  ;com1com:     resb 1 ; communication command for COM1
  2675                                  ;com2mode:    resb 1 ; communication mode for COM1
  2676                                  ;com2com      resb 1 ; communication command for COM1
  2677                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2678                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2679                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2680                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2681                                  
  2682                                  ; 22/08/2014 (RTC)
  2683                                  ; (Packed BCD)
  2684 000061AC ??                      time_seconds: resb 1
  2685 000061AD ??                      time_minutes: resb 1
  2686 000061AE ??                      time_hours:   resb 1
  2687 000061AF ??                      date_wday:    resb 1
  2688 000061B0 ??                      date_day:     resb 1
  2689 000061B1 ??                      date_month:   resb 1			
  2690 000061B2 ??                      date_year:    resb 1
  2691 000061B3 ??                      date_century: resb 1
  2692                                  
  2693                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2694                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKBSS.INC
  2695                              <1> ; Last Modification: 12/07/2022
  2696                              <1> ;	(Uninitialized Disk Parameters Data section for 'DISKIO.INC') 
  2697                              <1> ;
  2698                              <1> ; *****************************************************************************
  2699                              <1> ; Ref: Retro UNIX 386 v1.1 'disbss.inc' modification: 10/07/2022
  2700                              <1> 
  2701                              <1> 
  2702                              <1> alignb 2
  2703                              <1> 
  2704                              <1> ;----------------------------------------
  2705                              <1> ;	TIMER DATA AREA 		:
  2706                              <1> ;----------------------------------------
  2707                              <1> 
  2708                              <1> TIMER_LH:	; 16/02/205
  2709 000061B4 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2710 000061B6 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2711 000061B8 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2712                              <1> 
  2713                              <1> ;----------------------------------------
  2714                              <1> ;	DISKETTE DATA AREAS		:
  2715                              <1> ;----------------------------------------
  2716                              <1> 
  2717 000061B9 ??                  <1> SEEK_STATUS:	resb	1
  2718 000061BA ??                  <1> MOTOR_STATUS:	resb	1
  2719 000061BB ??                  <1> MOTOR_COUNT:	resb	1
  2720 000061BC ??                  <1> DSKETTE_STATUS:	resb	1
  2721 000061BD ??????????????      <1> NEC_STATUS:	resb	7
  2722                              <1> 
  2723                              <1> ;----------------------------------------
  2724                              <1> ;	ADDITIONAL MEDIA DATA		:
  2725                              <1> ;----------------------------------------
  2726                              <1> 
  2727 000061C4 ??                  <1> LASTRATE:	resb 	1
  2728 000061C5 ??                  <1> HF_STATUS:	resb 	1
  2729                              <1> ;HF_ERROR:	resb 	1  ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)	
  2730 000061C6 ??                  <1> HF_INT_FLAG:	resb	1
  2731                              <1> ;HF_CNTRL:	resb 	1  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2732                              <1> ;DSK_STATE:	resb 	4
  2733 000061C7 ????                <1> DSK_STATE:	resb 	2  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2734 000061C9 ????                <1> DSK_TRK:	resb 	2
  2735                              <1> 
  2736                              <1> ;----------------------------------------
  2737                              <1> ;	FIXED DISK DATA AREAS		:
  2738                              <1> ;----------------------------------------
  2739                              <1> 
  2740 000061CB ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2741 000061CC ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2742 000061CD ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2743                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2744                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2745                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2746                              <1> 
  2747 000061CE ????                <1> alignb 4
  2748                              <1> 
  2749                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2750                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2751                              <1> HF_TBL_VEC: ; 22/12/2014	
  2752 000061D0 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2753 000061D4 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2754 000061D8 ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2755 000061DC ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2756                              <1> 
  2757                              <1> ; 03/01/2015
  2758 000061E0 ??                  <1> LBAMode:     	resb	1
  2759                              <1> 
  2760                              <1> ; *****************************************************************************
  2694                                  
  2695                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2696                                  
  2697                                  ;alignb 2
  2698                                  
  2699                                  ; 27/02/2022
  2700                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2701                                  
  2702                                  ; 23/02/2022
  2703                                  ;; Memory (swap) Data (11/03/2015)
  2704                                  ; 09/03/2015
  2705                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2706                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2707                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  2708                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2709                                  ;swpd_next:  resd 1 ; next free page block
  2710                                  ;swpd_last:  resd 1 ; last swap page block	
  2711                                  
  2712 000061E1 ??????                  alignb 4
  2713                                  
  2714                                  ; 10/07/2015
  2715                                  ; 28/08/2014
  2716 000061E4 ????????                error_code:	resd 1
  2717                                  ; 29/08/2014
  2718 000061E8 ????????                FaultOffset: 	resd 1
  2719                                  ; 21/09/2015
  2720 000061EC ????????                PF_Count:	resd 1	; total page fault count
  2721                                  		       	; (for debugging - page fault analyze)
  2722                                  		 	; 'page _fault_handler' (memory.inc)
  2723                                  			; 'sysgeterr' (u9.s)
  2724                                  ; 23/02/2022
  2725 000061F0 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2726                                  			;  for a system call in next retro unix 386 version)
  2727                                  			; -2 ticks per second-
  2728                                  ;; 21/08/2015
  2729                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2730                                  
  2731                                  ; 27/02/2022
  2732                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2733                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYSX.INC (ux.s)
  2734                              <1> ; Last Modification: 15/07/2022
  2735                              <1> ;
  2736                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2737                              <1> ; (Modified from 
  2738                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2739                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2740                              <1> ; ----------------------------------------------------------------------------
  2741                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2742                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2743                              <1> ; <Bell Laboratories (17/3/1972)>
  2744                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2745                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2746                              <1> ; ****************************************************************************
  2747                              <1> ; 13/11/2015
  2748                              <1> 
  2749                              <1> alignb 2
  2750                              <1> 
  2751                              <1> inode:
  2752                              <1> 	; 11/03/2013. 
  2753                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2754                              <1> 	;i.
  2755                              <1> 
  2756 000061F4 ????                <1> 	i.flgs:	 resw 1
  2757 000061F6 ??                  <1> 	i.nlks:	 resb 1
  2758 000061F7 ??                  <1> 	i.uid:	 resb 1
  2759 000061F8 ????                <1>         i.size:  resw 1 ; size
  2760 000061FA <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2761 0000620A ????????            <1> 	i.ctim:	 resd 1
  2762 0000620E ????????            <1> 	i.mtim:	 resd 1
  2763 00006212 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2764                              <1> 
  2765                              <1> I_SIZE	equ $ - inode 
  2766                              <1> 
  2767                              <1> process:
  2768                              <1> 	; 26/02/2022
  2769                              <1> 	; 04/02/2022
  2770                              <1> 	; 06/05/2015
  2771                              <1> 	; 11/03/2013 - 05/02/2014
  2772                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2773                              <1> 	;p.
  2774                              <1> 	
  2775 00006214 <res 20h>           <1>         p.pid:   resw nproc
  2776 00006234 <res 20h>           <1>         p.ppid:  resw nproc
  2777                              <1>         ;p.break: resw nproc ; 04/02/2022 (p.break is not used)
  2778 00006254 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2779                              <1> 	; 26/02/2022 (p.waitc is not used)
  2780                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2781 00006264 <res 10h>           <1> 	p.link:	 resb nproc
  2782 00006274 <res 10h>           <1> 	p.stat:	 resb nproc
  2783                              <1> 
  2784                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2785 00006284 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2786                              <1> 			    ; 'user' structure	
  2787                              <1> 
  2788                              <1> 
  2789                              <1> P_SIZE	equ $ - process
  2790                              <1> 
  2791                              <1> 
  2792                              <1> ; fsp table (original UNIX v1)
  2793                              <1> ;
  2794                              <1> ;Entry
  2795                              <1> ;          15                                      0
  2796                              <1> ;  1     |---|---------------------------------------|
  2797                              <1> ;        |r/w|       i-number of open file           |
  2798                              <1> ;        |---|---------------------------------------| 
  2799                              <1> ;        |               device number               |
  2800                              <1> ;        |-------------------------------------------|
  2801                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2802                              <1> ;        |-------------------------------------------| 
  2803                              <1> ;        |  flag that says    | number of processes  |
  2804                              <1> ;        |   file deleted     | that have file open  |
  2805                              <1> ;        |-------------------------------------------| 
  2806                              <1> ;  2     |                                           |
  2807                              <1> ;        |-------------------------------------------| 
  2808                              <1> ;        |                                           |
  2809                              <1> ;        |-------------------------------------------|
  2810                              <1> ;        |                                           |
  2811                              <1> ;        |-------------------------------------------|
  2812                              <1> ;        |                                           |
  2813                              <1> ;        |-------------------------------------------| 
  2814                              <1> ;  3     |                                           | 
  2815                              <1> ;        |                                           |  
  2816                              <1> ;
  2817                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2818                              <1> 
  2819                              <1> 
  2820                              <1> ; 15/04/2015
  2821 000062C4 <res 1F4h>          <1> fsp:	 resb nfiles * 10 ; 11/05/2015 (8 -> 10)
  2822 000064B8 <res 28h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2823 000064E0 ????                <1> ii:	 resw 1
  2824 000064E2 ????                <1> idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2825 000064E4 ????                <1> cdev:    resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2826                              <1> ; 18/05/2015
  2827                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2828                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2829                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2830                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2831                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2832                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2833                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2834                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2835                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2836                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2837                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2838 000064E6 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2839                              <1> 	        ; as above, for physical drives numbers in following table
  2840 000064E7 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2841                              <1> ; 15/04/2015
  2842                              <1> ;active: resb 1 ; 15/07/2022
  2843                              <1> ;	 resb 1 ; 09/06/2015
  2844 000064E8 ????                <1> mnti:	 resw 1
  2845 000064EA ????                <1> mntp:	 resw 1 ; 14/05/2022 ; (parent dir inumber of [mnti])
  2846 000064EC ????                <1> mpid:	 resw 1
  2847 000064EE ????                <1> rootdir: resw 1
  2848                              <1> ; 14/02/2014
  2849                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2850                              <1> ;		      Single level run queue
  2851                              <1> ;		      (in order to solve sleep/wakeup lock)
  2852 000064F0 ????                <1> runq:	 resw 1
  2853 000064F2 ??                  <1> imod:	 resb 1
  2854 000064F3 ??                  <1> smod:	 resb 1
  2855 000064F4 ??                  <1> mmod:	 resb 1
  2856 000064F5 ??                  <1> sysflg:	 resb 1
  2857                              <1> 
  2858 000064F6 ????                <1> alignb 4
  2859                              <1> 
  2860                              <1> user:
  2861                              <1> 	; 18/10/2015
  2862                              <1> 	; 12/10/2015
  2863                              <1> 	; 21/09/2015
  2864                              <1> 	; 24/07/2015
  2865                              <1> 	; 16/06/2015
  2866                              <1> 	; 09/06/2015
  2867                              <1> 	; 11/05/2015
  2868                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2869                              <1> 	; 10/10/2013
  2870                              <1> 	; 11/03/2013. 
  2871                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2872                              <1> 	;u.
  2873                              <1> 
  2874 000064F8 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2875 000064FC ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2876 00006500 ????????            <1> 	u.r0:	  resd 1 ; eax
  2877 00006504 ????                <1> 	u.cdir:	  resw 1
  2878 00006506 <res Ah>            <1> 	u.fp:	  resb 10
  2879 00006510 ????????            <1> 	u.fofp:	  resd 1
  2880 00006514 ????????            <1> 	u.dirp:	  resd 1
  2881 00006518 ????????            <1> 	u.namep:  resd 1
  2882 0000651C ????????            <1> 	u.off:	  resd 1
  2883 00006520 ????????            <1> 	u.base:	  resd 1
  2884 00006524 ????????            <1> 	u.count:  resd 1
  2885 00006528 ????????            <1> 	u.nread:  resd 1
  2886 0000652C ????????            <1> 	u.break:  resd 1 ; break
  2887 00006530 ????                <1> 	u.ttyp:	  resw 1 
  2888 00006532 <res Ah>            <1> 	u.dirbuf: resb 10
  2889                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2890 0000653C ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2891 0000653D ??                  <1> 	u.pri:	  resb 1 ; 
  2892 0000653E ????                <1> 	u.intr:	  resw 1
  2893 00006540 ????                <1> 	u.quit:	  resw 1
  2894                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2895 00006542 ????                <1> 	u.ilgins: resw 1
  2896 00006544 ????                <1> 	u.cdrv:	  resw 1 ; cdev
  2897 00006546 ??                  <1> 	u.uid:	  resb 1 ; uid
  2898 00006547 ??                  <1> 	u.ruid:	  resb 1
  2899 00006548 ??                  <1> 	u.bsys:	  resb 1
  2900 00006549 ??                  <1> 	u.uno:	  resb 1
  2901 0000654A ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2902                              <1> 	; tty number (rtty, rcvt, wtty)
  2903 0000654E ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2904                              <1> 	; last error number
  2905 0000654F ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2906                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2907 00006553 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2908 00006557 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2909 0000655B ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2910 0000655F ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2911                              <1> 	;u.pncount: resw 1 
  2912                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2913                              <1> 	;u.pnbase:  resd 1 
  2914                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2915                              <1> 			 ; 09/06/2015
  2916 00006561 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2917 00006562 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2918                              <1> 			 ; 24/07/2015 - 24/06/2015
  2919                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2920                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2921                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2922                              <1>  			 ; 24/06/2015	  	
  2923                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2924                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2925                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2926 00006563 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2927                              <1> 
  2928 00006567 ??                  <1> alignb 4
  2929                              <1> 
  2930                              <1> U_SIZE	equ $ - user
  2931                              <1> 
  2932                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2933 00006568 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2934 0000656C ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2935 00006570 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2936 00006574 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2937 00006576 ????                <1> argc:	resw 1	; argument count for 'sysexec'
  2938 00006578 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2939                              <1> 
  2940                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2941                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2942 0000657C ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2943 0000657D ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2944 0000657E ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2945 0000657F ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2946                              <1> 
  2947                              <1> ;alignb 4
  2948                              <1> 
  2949                              <1> ; 22/08/2015
  2950 00006580 <res 1040h>         <1> buffer: resb nbuf * 520
  2951                              <1> 
  2952 000075C0 ????????????????    <1> sb0:	resd 2
  2953                              <1> ;s:
  2954                              <1> ; (root disk) super block buffer
  2955                              <1> systm:
  2956                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2957                              <1> 	; 11/03/2013. 
  2958                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  2959                              <1> 	;s.
  2960                              <1> 
  2961 000075C8 ????                <1> 	resw 1
  2962 000075CA <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  2963 00007732 ????                <1> 	resw 1
  2964 00007734 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  2965                              <1> eofitab equ $ - systm ; 12/02/2022 (end of inode table)
  2966 00007754 ????????            <1> 	s.time:	 resd 1
  2967 00007758 ????????            <1> 	s.syst:	 resd 1
  2968 0000775C ????????            <1>         s.wait_: resd 1 ; wait
  2969 00007760 ????????            <1> 	s.idlet: resd 1
  2970 00007764 ????????            <1> 	s.chrgt: resd 1
  2971 00007768 ????                <1> 	s.drerr: resw 1
  2972                              <1> 
  2973                              <1> S_SIZE	equ $ - systm
  2974                              <1> 
  2975 0000776A <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  2976                              <1> 
  2977 000077C8 ????????????????    <1> sb1:	resd 2
  2978                              <1> ; (mounted disk) super block buffer
  2979                              <1> mount:	
  2980 000077D0 <res 200h>          <1> 	resb 512  ; 03/06/2015
  2981                              <1> 
  2982                              <1> ;/ ux -- unix
  2983                              <1> ;
  2984                              <1> ;systm:
  2985                              <1> ;
  2986                              <1> ;	.=.+2
  2987                              <1> ;	.=.+128.
  2988                              <1> ;	.=.+2
  2989                              <1> ;	.=.+64.
  2990                              <1> ;	s.time: .=.+4
  2991                              <1> ;	s.syst: .=.+4
  2992                              <1> ;	s.wait: .=.+4
  2993                              <1> ;	s.idlet:.=.+4
  2994                              <1> ;	s.chrgt:.=.+4
  2995                              <1> ;	s.drerr:.=.+2
  2996                              <1> ;inode:
  2997                              <1> ;	i.flgs: .=.+2
  2998                              <1> ;	i.nlks: .=.+1
  2999                              <1> ;	i.uid:  .=.+1
  3000                              <1> ;	i.size: .=.+2
  3001                              <1> ;	i.dskp: .=.+16.
  3002                              <1> ;	i.ctim: .=.+4
  3003                              <1> ;	i.mtim: .=.+4
  3004                              <1> ;	. = inode+32.
  3005                              <1> ;mount:	.=.+1024.
  3006                              <1> ;proc:
  3007                              <1> ;	p.pid:  .=.+[2*nproc]
  3008                              <1> ;	p.dska: .=.+[2*nproc]
  3009                              <1> ;	p.ppid: .=.+[2*nproc]
  3010                              <1> ;	p.break:.=.+[2*nproc]
  3011                              <1> ;	p.link: .=.+nproc
  3012                              <1> ;	p.stat: .=.+nproc
  3013                              <1> ;tty:
  3014                              <1> ;	. = .+[ntty*8.]
  3015                              <1> ;fsp:	.=.+[nfiles*8.]
  3016                              <1> ;bufp:	.=.+[nbuf*2]+6
  3017                              <1> ;sb0:	.=.+8
  3018                              <1> ;sb1:	.=.+8
  3019                              <1> ;swp:	.=.+8
  3020                              <1> ;ii:	.=.+2
  3021                              <1> ;idev:	.=.+2
  3022                              <1> ;cdev:	.=.+2
  3023                              <1> ;deverr: .=.+12.
  3024                              <1> ;active: .=.+2
  3025                              <1> ;rfap:	.=.+2
  3026                              <1> ;rkap:	.=.+2
  3027                              <1> ;tcap:	.=.+2
  3028                              <1> ;tcstate:.=.+2
  3029                              <1> ;tcerrc: .=.+2
  3030                              <1> ;mnti:	.=.+2
  3031                              <1> ;mntd:	.=.+2
  3032                              <1> ;mpid:	.=.+2
  3033                              <1> ;clockp: .=.+2
  3034                              <1> ;rootdir:.=.+2
  3035                              <1> ;toutt:	.=.+16.
  3036                              <1> ;touts: .=.+32.
  3037                              <1> ;runq:	.=.+6
  3038                              <1> ;
  3039                              <1> ;wlist:	.=.+40.
  3040                              <1> ;cc:	.=.+30.
  3041                              <1> ;cf:	.=.+31.
  3042                              <1> ;cl:	.=.+31.
  3043                              <1> ;clist:	.=.+510.
  3044                              <1> ;imod:	.=.+1
  3045                              <1> ;smod:	.=.+1
  3046                              <1> ;mmod:	.=.+1
  3047                              <1> ;uquant: .=.+1
  3048                              <1> ;sysflg: .=.+1
  3049                              <1> ;pptiflg:.=.+1
  3050                              <1> ;ttyoch: .=.+1
  3051                              <1> ; .even
  3052                              <1> ; .=.+100.; sstack:
  3053                              <1> ;buffer: .=.+[ntty*140.]
  3054                              <1> ;	.=.+[nbuf*520.]
  3055                              <1> ;
  3056                              <1> ; . = core-64.
  3057                              <1> ;user:
  3058                              <1> ;	u.sp:    .=.+2
  3059                              <1> ;	u.usp:   .=.+2
  3060                              <1> ;	u.r0:    .=.+2
  3061                              <1> ;	u.cdir:  .=.+2
  3062                              <1> ;	u.fp:    .=.+10.
  3063                              <1> ;	u.fofp:  .=.+2
  3064                              <1> ;	u.dirp:  .=.+2
  3065                              <1> ;	u.namep: .=.+2
  3066                              <1> ;	u.off:   .=.+2
  3067                              <1> ;	u.base:  .=.+2
  3068                              <1> ;	u.count: .=.+2
  3069                              <1> ;	u.nread: .=.+2
  3070                              <1> ;	u.break: .=.+2
  3071                              <1> ;	u.ttyp:  .=.+2
  3072                              <1> ;	u.dirbuf:.=.+10.
  3073                              <1> ;	u.pri:   .=.+2
  3074                              <1> ;	u.intr:  .=.+2
  3075                              <1> ;	u.quit:  .=.+2
  3076                              <1> ;	u.emt:   .=.+2
  3077                              <1> ;	u.ilgins:.=.+2
  3078                              <1> ;	u.cdev:  .=.+2
  3079                              <1> ;	u.uid:   .=.+1
  3080                              <1> ;	u.ruid:  .=.+1
  3081                              <1> ;	u.bsys:  .=.+1
  3082                              <1> ;	u.uno:   .=.+1
  3083                              <1> ;. = core
  2733                                  
  2734                                  bss_end:
  2735                                  
  2736                                  ; 27/02/2022
  2737                                  BSS_SIZE equ bss_end - bss_start
  2738                                  
  2739                                  ; 27/12/2013
  2740                                  _end:  ; end of kernel code (and read only data, just before bss)
