     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.5
     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: 10/07/2022 (v0.2.1.5) ]
    13                                  ;	 04/02/2016 - Retro UNIX 386 v1.1 (Retro UNIX Kernel v0.2.1.0)	
    14                                  ;	 31/12/2021 - BugFix and Code Optimization (v0.2.1.1)
    15                                  ;	 03/03/2022 - Code Optimization and BugFix (v0.2.1.2) - 02/01/2022
    16                                  ;	 04/04/2022 - Inode Table/List Address Modification (v0.2.1.2) -u5.s-
    17                                  ;	 22/04/2022 - BugFix ('mget' -u5.s-)
    18                                  ;	 29/04/2022 - BugFix ('syschmod' -u2.s-) (v0.2.1.2)
    19                                  ;	 ; (v0.2.1.3)
    20                                  ;	 09/05/2022 - u2.s (systat), u7.s (sysumount), diskinit.inc  
    21                                  ;	 15/05/2022 - u2.s (namei), u7.s (sysumount)
    22                                  ;	 01/06/2022 - BugFix ('set_date_time' -u0.s-) (v0.2.1.3)
    23                                  ;	 ; (v0.2.1.4)
    24                                  ;	 13/06/2022 - LPT1 (/dev/lpr) printing modification (v0.2.1.4)
    25                                  ;	 14/06/2022 - BugFix (video.inc,'set_cpos' <- u9.s 'putc' carry flg)
    26                                  ;	 ; (v0.2.1.5)
    27                                  ;	 08/07/2022 - diskio.s (diskio simplified by removing the unused code) 
    28                                  ;
    29                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    30                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    31                                  ; <Bell Laboratories (17/3/1972)>
    32                                  ; <Preliminary Release of UNIX Implementation Document>
    33                                  ;
    34                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    35                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    36                                  ;
    37                                  ; ****************************************************************************
    38                                  ; 31/12/2021 - 15/05/2022
    39                                  ; nasm unix386.s -l unix386.txt -o unix386 -Z error.txt
    40                                  ; ('unixcopy' utility is used for updating retro unix kernel on runix fs disk)
    41                                  
    42                                  ; 02/01/2022 - Code Optimization
    43                                  ; Runix Kernel v0.2.1.2
    44                                  ; 24/12/2021 - BugFix and Code Optimization
    45                                  ; Runix Kernel v0.2.1.1 
    46                                  
    47                                  ; 24/12/2013
    48                                  
    49                                  ; Entering protected mode:
    50                                  ; Derived from 'simple_asm.txt' source code file and 
    51                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    52                                  ; (gregor.brunmar@home.se)
    53                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    54                                  ;
    55                                  
    56                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    57                                  ; by Michael Chourdakis (2009) 
    58                                  ; http://www.codeproject.com/Articles/45788/
    59                                  ; http://www.michaelchourdakis.com
    60                                  ;
    61                                  
    62                                  ; Global Descriptor Table:
    63                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    64                                  ; by Linus Torvalds (1991-1992)
    65                                  ;
    66                                  
    67                                  KLOAD	equ 10000h ; Kernel loading address
    68                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h
    69                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    70                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    71                                  ; 19/03/2015
    72                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    73                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    74                                  ; 24/03/2015
    75                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    76                                  ; 19/03/2015
    77                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    78                                  		     ; (at the end of the 1st 4MB)
    79                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    80                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    81                                  
    82                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
    83                                  ;; 27/12/2013
    84                                  ;KEND	equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    85                                  
    86                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    87                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    88                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    89                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    90                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    91                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    92                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    93                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    94                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    95                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    96                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    97                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    98                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    99                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
   100                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
   101                                  ;----------------------------------------
   102                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
   103                                  ;-----------------------------------------------------------------------------
   104                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
   105                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
   106                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
   107                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
   108                                  
   109                                  ; Memory Allocation Table Address
   110                                  ; 05/11/2014
   111                                  ; 31/10/2014
   112                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
   113                                  					; the 1st 1 MB memory space.
   114                                  					; (This address must be aligned
   115                                  					;  on 128 KB boundary, if it will be
   116                                  					;  changed later.)
   117                                  					; ((lower 17 bits of 32 bit M.A.T.
   118                                  					;   address must be ZERO)).
   119                                  					; ((((Reason: 32 bit allocation 
   120                                  					;     instructions, dword steps)))
   121                                  					; (((byte >> 12 --> page >> 5)))  
   122                                  ;04/11/2014	
   123                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   124                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   125                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   126                                  ;
   127                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   128                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   129                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   130                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   131                                  
   132                                  ; 17/02/2015 (unix386.s)
   133                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   134                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   135                                  ;
   136                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   137                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   138                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   139                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   140                                  
   141                                  
   142                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   143                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   144                                  ;
   145                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   146                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   147                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   148                                  		      ; otherwise it is standard FDPT with physical values 	
   149                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   150                                  		      ; (obsolete for IDE/ATA drives)
   151                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   152                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   153                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   154                                  			; Bit 4 : Reserved. Always 0
   155                                  			; Bit 3 : Set to 1 if more than 8 heads
   156                                  			; Bit 2-0 : Reserved. Alsways 0
   157                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   158                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   159                                  
   160                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   161                                  ; (11 bytes long) will be used by diskette handler/bios
   162                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   163                                  
   164                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   165                                  
   166                                  [ORG 0]
   167                                  
   168                                  KSTART: ; 01/01/2022
   169                                   
   170                                  	; 12/11/2014
   171                                  	; Save boot drive number (that is default root drive)
   172 00000000 8816[CA5F]              	mov	[boot_drv], dl ; physical drv number
   173                                  
   174                                  	; Determine installed memory
   175                                  	; 31/10/2014
   176                                  	;
   177 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   178 00000007 CD15                    	int	15h	   ; for large configurations
   179 00000009 7308                    	jnc	short chk_ms
   180 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   181 0000000D CD15                    	int	15h
   182                                  	;	   
   183                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   184                                  	;out	70h, al ; select CMOS register
   185                                  	;in	al, 71h ; read data (1 byte)
   186                                  	;mov	cl, al
   187                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   188                                  	;out	70h, al ; select CMOS register
   189                                  	;in	al, 71h ; read data (1 byte)
   190                                  	;mov	ch, al
   191                                   	;      
   192 0000000F 89C1                    	mov	cx, ax
   193 00000011 31D2                    	xor	dx, dx
   194                                  chk_ms:
   195 00000013 890E[6062]              	mov	[mem_1m_1k], cx
   196 00000017 8916[6462]              	mov	[mem_16m_64k], dx
   197                                  	; 05/11/2014
   198                                  	;and	dx, dx
   199                                  	;jz	short L2
   200 0000001B 81F90004                        cmp     cx, 1024
   201 0000001F 7351                    	jnb	short L0
   202                                  		 ; insufficient memory_error	
   203                                  		 ; Minimum 2 MB memory is needed... 
   204                                  	; 05/11/2014
   205                                  	; (real mode error printing)
   206 00000021 FB                      	sti
   207 00000022 BE[3600]                	mov	si, msg_out_of_memory
   208 00000025 BB0700                  	mov	bx, 7
   209 00000028 B40E                    	mov	ah, 0Eh	; write tty
   210                                  oom_1:
   211 0000002A AC                      	lodsb
   212 0000002B 08C0                    	or	al, al
   213 0000002D 7404                    	jz	short oom_2
   214 0000002F CD10                    	int	10h
   215 00000031 EBF7                    	jmp	short oom_1
   216                                  oom_2:
   217 00000033 F4                              hlt
   218 00000034 EBFD                    	jmp	short oom_2
   219                                  
   220                                  ; 02/01/2022
   221                                  ; 05/11/2014
   222                                  msg_out_of_memory:
   223 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   224 00000039 496E73756666696369-             db      'Insufficient memory !'
   224 00000042 656E74206D656D6F72-
   224 0000004B 792021             
   225 0000004E 0D0A                    	db	0Dh, 0Ah
   226                                  _int13h_48h_buffer: ; 02/01/2022 (Runix Kernel v0.2.1.2, 'diskinit.inc')
   227 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   227 00000059 324D42206D656D6F72-
   227 00000062 79206973206E656564-
   227 0000006B 65642E29           
   228 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   229                                  
   230                                  L0:
   231                                  %include 'diskinit.inc' ; 07/03/2015
   232                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - DISKINIT.INC
   233                              <1> ; Last Modification: 09/05/2022
   234                              <1> 
   235                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   236                              <1> 
   237                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   238                              <1> 
   239                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   240                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   241                              <1> ;L0:
   242                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   243                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   244 00000072 BA7F00              <1> 	mov	dx, 7Fh
   245                              <1> L1:	
   246 00000075 FEC2                <1> 	inc	dl
   247 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   248                              <1> 			; Phoenix EDD v1.1 - EDD v3
   249 00000079 BBAA55              <1> 	mov	bx, 55AAh
   250 0000007C CD13                <1> 	int 	13h
   251 0000007E 721A                <1> 	jc	short L2
   252                              <1> 
   253 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   254 00000084 7514                <1> 	jne	short L2
   255 00000086 FE06[CD5F]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   256 0000008A 8816[CC5F]          <1>         mov     [last_drv], dl  ; last hard disk number
   257 0000008E BB[505F]            <1> 	mov	bx, hd0_type - 80h
   258 00000091 01D3                <1> 	add	bx, dx	 
   259 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   260                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   261                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   262                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   263                              <1>                          ;            (EDD) ready (DPTE ready)
   264                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   265                              <1>                          ;            (EDD-3)
   266                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   267 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   268 00000098 72DB                <1> 	jb	short L1
   269                              <1> L2:
   270                              <1> 	; 23/11/2014
   271                              <1> 	; 19/11/2014
   272 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   273                              <1> 	; 04/02/2016 (esi -> si)
   274 0000009C BE[CE5F]            <1> 	mov	si, fd0_type
   275                              <1> L3:
   276                              <1> 	; 14/01/2015
   277 0000009F 8816[CB5F]          <1> 	mov	[drv], dl
   278                              <1> 	;
   279 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   280 000000A5 CD13                <1> 	int	13h	
   281 000000A7 7210                <1> 	jc	short L4
   282                              <1> 		; BL = drive type (for floppy drives)
   283                              <1> 		; DL = number of floppy drives
   284                              <1> 		;		
   285                              <1> 		; ES:DI = Address of DPT from BIOS
   286                              <1> 		;
   287 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   288                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   289                              <1> 	; 14/01/2015
   290 000000AB E8BB01              <1> 	call	set_disk_parms
   291                              <1> 	; 10/12/2014
   292 000000AE 81FE[CE5F]          <1> 	cmp	si, fd0_type
   293 000000B2 7705                <1> 	ja	short L4
   294 000000B4 46                  <1> 	inc	si ; fd1_type
   295 000000B5 B201                <1> 	mov	dl, 1
   296 000000B7 EBE6                <1> 	jmp	short L3
   297                              <1> L4:
   298                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   299 000000B9 B27F                <1> 	mov	dl, 7Fh
   300                              <1> 	; 24/12/2014 (Temporary)
   301 000000BB 803E[CD5F]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   302                              <1> 	;ja	L10       ; yes, all fixed disk operations
   303                              <1> 			  ; will be performed according to
   304                              <1> 			  ; present EDD specification
   305                              <1> 	; 02/01/2022
   306 000000C0 7603                <1> 	jna	short L5
   307 000000C2 E99100              <1> 	jmp	L10
   308                              <1> L5:
   309 000000C5 FEC2                <1> 	inc 	dl
   310 000000C7 8816[CB5F]          <1>         mov     [drv], dl
   311 000000CB 8816[CC5F]          <1>         mov     [last_drv], dl ; 14/01/2015
   312 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   313 000000D1 CD13                <1> 	int	13h	; (conventional function)
   314                              <1> 	;jc	L13	; fixed disk drive not ready
   315                              <1> 	; 02/01/2022
   316 000000D3 7303                <1> 	jnc	short L6
   317 000000D5 E98301              <1> 	jmp	L13
   318                              <1> L6:
   319 000000D8 8816[CD5F]          <1>         mov     [hdc], dl ; number of drives
   320                              <1> 	;; 14/01/2013
   321                              <1> 	;;push	cx
   322 000000DC E88A01              <1> 	call	set_disk_parms
   323                              <1> 	;;pop	cx
   324                              <1> 	;
   325                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   326 000000DF 8A16[CB5F]          <1>         mov     dl, [drv]
   327 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   328 000000E6 80FA80              <1> 	cmp	dl, 80h
   329 000000E9 7603                <1> 	jna	short L7
   330 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   331                              <1> L7:	
   332 000000EE 31C0                <1> 	xor	ax, ax
   333 000000F0 8ED8                <1> 	mov	ds, ax
   334 000000F2 8B37                <1>         mov     si, [bx]
   335 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   336 000000F7 8ED8                <1> 	mov	ds, ax
   337 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   338                              <1> 	;jne	L12 ; invalid FDPT
   339                              <1> 	; 02/01/2022
   340 000000FC 7403                <1> 	je	short L7_8
   341 000000FE E95601              <1> 	jmp	L12
   342                              <1> L7_8:
   343 00000101 BF0000              <1> 	mov	di, HD0_DPT
   344 00000104 80FA80              <1> 	cmp	dl, 80h
   345 00000107 7603                <1> 	jna	short L8
   346 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   347                              <1> L8:
   348                              <1> 	; 30/12/2014
   349 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   350 0000010F 8EC0                <1> 	mov	es, ax
   351                              <1> 	; 24/12/2014
   352 00000111 B90800              <1> 	mov	cx, 8
   353 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   354 00000116 8CC8                <1> 	mov	ax, cs
   355 00000118 8ED8                <1> 	mov	ds, ax
   356                              <1> 	; 02/02/2015
   357 0000011A 8A0E[CB5F]          <1>         mov     cl, [drv]
   358 0000011E 88CB                <1> 	mov	bl, cl
   359 00000120 B8F001              <1> 	mov	ax, 1F0h
   360 00000123 80E301              <1> 	and	bl, 1
   361 00000126 7406                <1> 	jz	short L9
   362 00000128 C0E304              <1> 	shl	bl, 4
   363 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   364                              <1> L9:
   365 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   366 0000012F 050602              <1> 	add	ax, 206h
   367 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   368 00000133 88D8                <1> 	mov	al, bl
   369 00000135 04A0                <1> 	add	al, 0A0h
   370 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   371                              <1> 	;
   372 00000138 FE06[CB5F]          <1> 	inc	byte [drv]
   373 0000013C BB[505F]            <1> 	mov	bx, hd0_type - 80h
   374 0000013F 01CB                <1> 	add	bx, cx
   375 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   376 00000144 A0[CD5F]            <1> 	mov	al, [hdc]
   377 00000147 FEC8                <1> 	dec	al
   378                              <1> 	;jz	L13
   379                              <1> 	; 02/01/2022
   380 00000149 7408                <1> 	jz	short L9_10
   381 0000014B 80FA80              <1> 	cmp	dl, 80h
   382                              <1>         ;jna	L5
   383                              <1> 	;jmp	L13
   384                              <1> 	; 02/01/2022
   385 0000014E 7703                <1> 	ja	short L9_10
   386 00000150 E972FF              <1> 	jmp	L5
   387                              <1> L9_10:
   388 00000153 E90501              <1>         jmp     L13
   389                              <1> L10:
   390 00000156 FEC2                <1> 	inc 	dl
   391                              <1> 	; 25/12/2014
   392 00000158 8816[CB5F]          <1> 	mov	[drv], dl
   393 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   394 0000015E CD13                <1> 	int	13h	; (conventional function)
   395                              <1> 	;jc	L13
   396                              <1> 	; 02/01/2022
   397 00000160 72F1                <1> 	jc	short L9_10
   398                              <1> 	; 14/01/2015
   399 00000162 8A16[CB5F]          <1> 	mov	dl, [drv]
   400 00000166 52                  <1> 	push	dx
   401 00000167 51                  <1> 	push	cx
   402 00000168 E8FE00              <1> 	call	set_disk_parms
   403 0000016B 59                  <1> 	pop	cx
   404 0000016C 5A                  <1> 	pop	dx
   405                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   406                              <1> 	; 04/02/2016 (esi -> si)
   407                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   408                              <1> 	;		 ; at the '_end' of kernel.
   409                              <1> 	;mov	word [si], 30
   410                              <1> 	; 06/07/2016
   411 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   412                              <1> 	; 09/07/2016
   413 00000170 B81E00              <1> 	mov	ax, 001Eh
   414 00000173 8824                <1> 	mov	[si], ah ; 0
   415 00000175 46                  <1> 	inc	si
   416 00000176 8904                <1> 	mov	word [si], ax
   417                              <1>  	; word [si] = 30
   418                              <1> 	;
   419 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   420 0000017A CD13                <1> 	int	13h
   421                              <1>         ;jc	L13
   422                              <1> 	; 02/01/2022
   423 0000017C 72D5                <1> 	jc	short L9_10
   424                              <1> 	; 04/02/2016 (ebx -> bx)
   425                              <1> 	; 14/01/2015
   426                              <1> 	;sub	bx, bx
   427 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   428 00000180 88D3                <1> 	mov	bl, dl
   429 00000182 80EB80              <1> 	sub	bl, 80h
   430 00000185 81C3[D05F]          <1> 	add	bx, hd0_type
   431 00000189 8A07                <1> 	mov 	al, [bx]
   432 0000018B 0C80                <1> 	or	al, 80h
   433 0000018D 8807                <1> 	mov 	[bx], al	
   434 0000018F 81EB[CE5F]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   435 00000193 81C3[1A60]          <1> 	add	bx, drv.status
   436 00000197 8807                <1> 	mov	[bx], al
   437                              <1> 	; 04/02/2016 (eax -> ax)
   438 00000199 8B4410              <1> 	mov	ax, [si+16]
   439 0000019C 854412              <1> 	test	ax, [si+18]
   440 0000019F 7413                <1> 	jz	short L10_A0h 
   441                              <1> 			; 'CHS only' disks on EDD system 
   442                              <1> 			;  are reported with ZERO disk size
   443 000001A1 81EB[1A60]          <1> 	sub	bx, drv.status
   444 000001A5 C1E302              <1> 	shl	bx, 2
   445 000001A8 81C3[FE5F]          <1> 	add	bx, drv.size ; disk size (in sectors)
   446 000001AC 8907                <1> 	mov	[bx], ax
   447 000001AE 8B4412              <1> 	mov	ax, [si+18]
   448                              <1> 	;mov	[bx], ax
   449                              <1> 	; 02/01/2022 (BugFix)
   450 000001B1 894702              <1> 	mov	[bx+2], ax
   451                              <1> 
   452                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   453                              <1> 	 ; for CHS disks (28/02/2015)
   454                              <1> 	; 30/12/2014
   455 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   456 000001B7 88D0                <1> 	mov	al, dl
   457 000001B9 83E003              <1> 	and 	ax, 3
   458 000001BC C0E005              <1> 	shl	al, 5 ; *32
   459 000001BF 01C7                <1> 	add 	di, ax
   460 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   461 000001C4 8EC0                <1> 	mov	es, ax
   462                              <1> 	;
   463 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   464 000001C8 88CC                <1> 	mov	ah, cl	
   465 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   466 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   467 000001CE AB                  <1> 	stosw		
   468 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   469 000001D1 FEC0                <1> 	inc	al
   470 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   471 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   472 000001D6 AA                  <1> 	stosb
   473 000001D7 8A440C              <1> 	mov	al, [si+12]
   474 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   475 000001DB 31C0                <1>  	xor	ax, ax
   476                              <1> 	;dec	ax	 ; 02/01/2015 
   477 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   478                              <1> 	;xor	al, al	 ; 02/01/2015	
   479 000001DE AA                  <1> 	stosb		 ; reserved
   480 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   481                              <1> 		         ; (do not disable retries, 
   482                              <1> 			 ; more than 8 heads)
   483 000001E1 AA                  <1> 	stosb
   484 000001E2 8B4404              <1> 	mov	ax, [si+4]
   485 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   486                              <1> 	;push	ax	 ; 02/01/2015
   487 000001E6 8A4408              <1> 	mov	al, [si+8]
   488 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   489 000001EA 29C0                <1> 	sub 	ax, ax
   490                              <1> 	;pop	ax	 ; 02/01/2015	
   491 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   492 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   493 000001EF 243F                <1> 	and 	al, 3Fh	
   494 000001F1 AA                  <1> 	stosb
   495                              <1> 	;sub	al, al	 ; checksum
   496                              <1> 	;stosb
   497                              <1> 	;
   498 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   499 000001F5 AD                  <1> 	lodsw
   500 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   501 000001F7 AD                  <1> 	lodsw
   502 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   503                              <1> 	;
   504                              <1> 	; checksum calculation
   505 000001F9 89FE                <1> 	mov	si, di
   506 000001FB 06                  <1> 	push	es
   507 000001FC 1F                  <1> 	pop	ds
   508                              <1> 	;mov	cx, 16
   509 000001FD B90F00              <1> 	mov 	cx, 15
   510 00000200 29CE                <1> 	sub	si, cx
   511 00000202 30E4                <1> 	xor	ah, ah
   512                              <1> 	;del	cl
   513                              <1> L11:		
   514 00000204 AC                  <1> 	lodsb
   515 00000205 00C4                <1> 	add	ah, al
   516 00000207 E2FB                <1> 	loop	L11
   517                              <1> 	;
   518 00000209 88E0                <1> 	mov	al, ah
   519 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   520 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   521                              <1> 	;
   522 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   523 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   524                              <1> 	;
   525                              <1> 	; 23/02/2015
   526 00000210 57                  <1> 	push	di
   527                              <1> 	; ES:DI points to DPTE (FDPTE) location
   528                              <1> 	;mov	cx, 8
   529 00000211 B108                <1> 	mov	cl, 8
   530 00000213 F3A5                <1> 	rep	movsw	
   531                              <1> 	;
   532                              <1> 	; 23/02/2015
   533                              <1> 	; (P)ATA drive and LBA validation
   534                              <1> 	; (invalidating SATA drives and setting
   535                              <1> 	; CHS type I/O for old type fixed disks)
   536 00000215 5B                  <1> 	pop	bx
   537 00000216 8CC8                <1> 	mov	ax, cs
   538 00000218 8ED8                <1> 	mov	ds, ax
   539 0000021A 268B07              <1> 	mov	ax, [es:bx]
   540 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   541 00000220 7418                <1> 	je	short L11a
   542 00000222 3D7001              <1> 	cmp	ax, 170h
   543 00000225 7413                <1> 	je	short L11a
   544                              <1> 	; invalidation 
   545                              <1> 	; (because base port address is not 1F0h or 170h)
   546 00000227 30FF                <1> 	xor	bh, bh
   547 00000229 88D3                <1> 	mov	bl, dl
   548 0000022B 80EB80              <1> 	sub	bl, 80h
   549 0000022E C687[D05F]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   550 00000233 808F[1C60]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   551 00000238 EB14                <1> 	jmp	short L11b
   552                              <1> L11a:	
   553                              <1> 	; LBA validation
   554 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   555 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   556 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   557                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   558 00000242 28FF                <1> 	sub	bh, bh
   559 00000244 88D3                <1> 	mov	bl, dl
   560 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   561 00000249 80A7[1C60]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   562                              <1> 				; bit 0 = LBA ready bit
   563                              <1> 	; 'diskio' procedure will check this bit !
   564                              <1> L11b:
   565 0000024E 3A16[CC5F]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   566 00000252 7307                <1>         jnb     short L13
   567 00000254 E9FFFE              <1>         jmp     L10
   568                              <1> L12:
   569                              <1> 	; Restore data registers
   570 00000257 8CC8                <1> 	mov	ax, cs
   571 00000259 8ED8                <1> 	mov	ds, ax	
   572                              <1> L13:
   573                              <1> 	; 13/12/2014
   574 0000025B 0E                  <1> 	push	cs
   575 0000025C 07                  <1> 	pop	es
   576                              <1> L14:
   577 0000025D B411                <1> 	mov 	ah, 11h
   578 0000025F CD16                <1> 	int 	16h
   579                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   580                              <1> 	; 02/01/2022
   581 00000261 7465                <1> 	jz	short L16
   582 00000263 B010                <1> 	mov	al, 10h
   583 00000265 CD16                <1> 	int 	16h
   584 00000267 EBF4                <1> 	jmp 	short L14
   585                              <1> L15:
   586                              <1> 
   587                              <1> ; //////
   588                              <1> 
   589                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   590                              <1> %if 0
   591                              <1> 	; 24/11/2014
   592                              <1> 	; 19/11/2014
   593                              <1> 	; 14/11/2014
   594                              <1> 	; Temporary code for disk searching code check
   595                              <1> 	;
   596                              <1> 	; This code will show existing (usable) drives and also
   597                              <1> 	; will show EDD interface support status for hard disks		
   598                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   599                              <1> 	; no need to get it again in protected mode...) 
   600                              <1> 	;	
   601                              <1> 	; 13/11/2014
   602                              <1> 	mov	bx, 7
   603                              <1> 	mov	ah, 0Eh
   604                              <1> 	mov	al, [fd0_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, '0'
   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> 	;
   620                              <1> 	mov	al, [fd1_type]
   621                              <1> 	and	al, al
   622                              <1> 	jz	short L15a
   623                              <1> 	mov	dl, al
   624                              <1> 	mov	al, 'F'
   625                              <1> 	int 	10h
   626                              <1> 	mov	al, 'D'
   627                              <1> 	int 	10h
   628                              <1> 	mov	al, '1'
   629                              <1> 	int 	10h
   630                              <1> 	mov	al, ' '
   631                              <1> 	int	10h
   632                              <1> 	call	L15c
   633                              <1> 	mov	al, ' '
   634                              <1> 	int	10h
   635                              <1> 	mov	al, ' '
   636                              <1> 	int	10h
   637                              <1> L15a:
   638                              <1> 	mov	al, [hd0_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, '0'
   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, [hd1_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, '1'
   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, [hd2_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, '2'
   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> 	mov	al, [hd3_type]
   687                              <1> 	and	al, al
   688                              <1> 	jz	short L15b
   689                              <1> 	mov	dl, al
   690                              <1> 	mov	al, 'H'
   691                              <1> 	int 	10h
   692                              <1> 	mov	al, 'D'
   693                              <1> 	int 	10h
   694                              <1> 	mov	al, '3'
   695                              <1> 	int 	10h
   696                              <1> 	mov	al, ' '
   697                              <1> 	int 	10h
   698                              <1> 	call	L15c
   699                              <1> 	mov	al, ' '
   700                              <1> 	int	10h
   701                              <1> 	;
   702                              <1> L15b:
   703                              <1> 	mov	al, 0Dh
   704                              <1> 	int 	10h	
   705                              <1> 	mov	al, 0Ah
   706                              <1> 	int 	10h
   707                              <1> 	;;xor	ah, ah
   708                              <1> 	;;int 	16h	
   709                              <1> 	;
   710                              <1>         ;jmp	L16  ; jmp short L16
   711                              <1>         ; 02/01/2022
   712                              <1> 	jmp	short L16
   713                              <1> 	;
   714                              <1> L15c:
   715                              <1> 	mov	dh, dl
   716                              <1> 	shr	dh, 4
   717                              <1> 	add	dh, 30h
   718                              <1> 	and	dl, 15
   719                              <1> 	add	dl, 30h
   720                              <1> 	mov	al, dh
   721                              <1> 	int	10h
   722                              <1> 	mov	al, dl
   723                              <1> 	int	10h
   724                              <1> 	retn
   725                              <1> 	;
   726                              <1> 	; end of temporary code for disk searching code check
   727                              <1> 
   728                              <1> %endif
   729                              <1> 
   730                              <1> ; //////
   731                              <1> 
   732                              <1> set_disk_parms:
   733                              <1> 	; 09/05/2022
   734                              <1> 	;	disksize = cylinders*spt*heads (*)
   735                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders) 
   736                              <1> 	;
   737                              <1> 	; 04/02/2016 (ebx -> bx)
   738                              <1> 	; 10/07/2015
   739                              <1> 	; 14/01/2015
   740                              <1> 	;push	bx
   741 00000269 28FF                <1> 	sub	bh, bh
   742 0000026B 8A1E[CB5F]          <1> 	mov	bl, [drv]
   743 0000026F 80FB80              <1> 	cmp	bl, 80h
   744 00000272 7203                <1> 	jb	short sdp0
   745 00000274 80EB7E              <1> 	sub	bl, 7Eh
   746                              <1> sdp0:	
   747 00000277 81C3[1A60]          <1> 	add	bx, drv.status
   748 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   749                              <1> 	;
   750 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   751 00000280 88CC                <1> 	mov	ah, cl ; 
   752 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   753 00000285 81EB[1A60]          <1> 	sub	bx, drv.status
   754 00000289 D0E3                <1> 	shl	bl, 1
   755 0000028B 81C3[D45F]          <1> 	add	bx, drv.cylinders
   756 0000028F 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   757 00000290 8907                <1> 	mov	[bx], ax
   758 00000292 50                  <1> 	push	ax ; ** cylinders
   759 00000293 81EB[D45F]          <1> 	sub	bx, drv.cylinders
   760 00000297 81C3[E25F]          <1> 	add	bx, drv.heads
   761 0000029B 30E4                <1> 	xor	ah, ah
   762 0000029D 88F0                <1> 	mov	al, dh ; heads
   763 0000029F 40                  <1> 	inc	ax
   764 000002A0 8907                <1> 	mov	[bx], ax
   765 000002A2 81EB[E25F]          <1>         sub     bx, drv.heads
   766 000002A6 81C3[F05F]          <1>         add     bx, drv.spt
   767 000002AA 30ED                <1> 	xor	ch, ch
   768 000002AC 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   769 000002AF 890F                <1> 	mov	[bx], cx
   770 000002B1 81EB[F05F]          <1>         sub     bx, drv.spt
   771 000002B5 D1E3                <1> 	shl	bx, 1
   772 000002B7 81C3[FE5F]          <1> 	add	bx, drv.size ; disk size (in sectors)
   773                              <1> 	; LBA size = cylinders * heads * secpertrack
   774 000002BB F7E1                <1> 	mul	cx 
   775 000002BD 89C2                <1> 	mov	dx, ax	; heads*spt					
   776 000002BF 58                  <1> 	pop	ax ; ** cylinders
   777                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   778                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   779 000002C0 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   780 000002C2 8907                <1> 	mov	[bx], ax
   781 000002C4 895702              <1> 	mov	[bx+2], dx
   782                              <1> 	;
   783                              <1> 	;pop	bx
   784 000002C7 C3                  <1> 	retn
   785                              <1> 
   786                              <1> ;align 2
   787                              <1> 
   788                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   789                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   790                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   791                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   792                              <1> 
   793                              <1> ;last_drv:
   794                              <1> ;	db  0
   795                              <1> ;drv_status:
   796                              <1> ;	db  0,0,0,0,0,0
   797                              <1> ;	db 0
   798                              <1> 
   799                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   800                              <1> 
   801                              <1> L16:
   232                                  
   233                                  	; 10/11/2014
   234 000002C8 FA                           	cli	; Disable interrupts (clear interrupt flag)
   235                                  		; Reset Interrupt MASK Registers (Master&Slave)
   236                                  	;mov	al, 0FFh	; mask off all interrupts
   237                                  	;out	21h, al		; on master PIC (8259)
   238                                  	;jmp 	$+2  ; (delay)
   239                                  	;out	0A1h, al	; on slave PIC (8259)
   240                                  	;
   241                                  	; Disable NMI 
   242 000002C9 B080                    	mov   	al, 80h 
   243 000002CB E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   244                                  	;23/02/2015
   245 000002CD 90                      	nop			;
   246                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   247                                  				; for preventing unknown state (!?)
   248                                  
   249                                  	; 02/01/2022
   250                                  	%define KERNELFSIZE KEND-KSTART 
   251                                  	;
   252                                   	; 20/08/2014
   253                                  	; Moving the kernel 64 KB back (to physical address 0)
   254                                  	; DS = CS = 1000h
   255                                  	; 05/11/2014
   256 000002CE 31C0                    	xor	ax, ax
   257 000002D0 8EC0                    	mov	es, ax ; ES = 0
   258                                  	;
   259                                  	;;mov	cx, (KEND - KLOAD)/4
   260                                  	;mov	cx, (KERNELFSIZE+3)/4 ; 02/01/2022
   261 000002D2 B93431                  	mov	cx, (KERNELFSIZE+1)/2 ; 02/01/2022
   262 000002D5 31F6                    	xor	si, si
   263 000002D7 31FF                    	xor	di, di
   264                                  	;rep	movsd
   265 000002D9 F3A5                    	rep	movsw ; 02/01/2022
   266                                  	;
   267 000002DB 06                      	push	es ; 0
   268 000002DC 68[E002]                	push	L17
   269 000002DF CB                      	retf
   270                                  	;
   271                                  L17:
   272                                  	; Turn off the floppy drive motor
   273 000002E0 BAF203                          mov     dx, 3F2h
   274 000002E3 EE                              out     dx, al ; 0 ; 31/12/2013
   275                                  
   276                                  	; Enable access to memory above one megabyte
   277                                  L18:
   278 000002E4 E464                    	in	al, 64h
   279 000002E6 A802                    	test	al, 2
   280 000002E8 75FA                            jnz     short L18
   281 000002EA B0D1                    	mov	al, 0D1h	; Write output port
   282 000002EC E664                    	out	64h, al
   283                                  L19:
   284 000002EE E464                    	in	al, 64h
   285 000002F0 A802                    	test	al, 2
   286 000002F2 75FA                            jnz     short L19
   287 000002F4 B0DF                    	mov	al, 0DFh	; Enable A20 line
   288 000002F6 E660                    	out	60h, al
   289                                  ;L20:
   290                                  	;
   291                                  	; Load global descriptor table register
   292                                  
   293                                          ;mov     ax, cs
   294                                          ;mov     ds, ax
   295                                  
   296 000002F8 2E0F0116[F05C]                  lgdt    [cs:gdtd]
   297                                  
   298 000002FE 0F20C0                          mov     eax, cr0
   299                                  	; or 	eax, 1
   300 00000301 40                      	inc     ax
   301 00000302 0F22C0                  	mov     cr0, eax
   302                                  
   303                                  	; Jump to 32 bit code
   304                                  	
   305 00000305 66                      	db 66h 			; Prefix for 32-bit
   306 00000306 EA                      	db 0EAh 		; Opcode for far jump
   307 00000307 [0D030000]              	dd StartPM 		; Offset to start, 32-bit
   308                                  				; (1000h:StartPM = StartPM + 10000h)
   309 0000030B 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   310                                  				; assuming that StartPM resides in code32
   311                                  
   312                                  [BITS 32] 
   313                                  
   314                                  StartPM:
   315                                  	; Kernel Base Address = 0 ; 30/12/2013
   316 0000030D 66B81000                	mov ax, KDATA           ; Save data segment identifier
   317 00000311 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   318 00000313 8EC0                           	mov es, ax              ; Move data segment into ES register
   319 00000315 8EE0                           	mov fs, ax              ; Move data segment into FS register
   320 00000317 8EE8                          	mov gs, ax              ; Move data segment into GS register
   321 00000319 8ED0                            mov ss, ax              ; Move data segment into SS register
   322 0000031B BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   323                                  
   324                                  clear_bss: ; Clear uninitialized data area
   325                                  	; 11/03/2015
   326 00000320 31C0                    	xor	eax, eax ; 0
   327                                  	;mov	ecx, (bss_end - bss_start)/4
   328                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   329                                  	; 02/01/2022
   330 00000322 B9BC050000              	mov	ecx, BSS_SIZE/4
   331 00000327 BF[70620000]            	mov	edi, bss_start
   332 0000032C F3AB                    	rep	stosd  		
   333                                  
   334                                  memory_init:
   335                                  	; Initialize memory allocation table and page tables
   336                                  	;
   337                                  	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   338                                  	; 16/11/2014
   339                                  	; 15/11/2014
   340                                  	; 07/11/2014
   341                                  	; 06/11/2014
   342                                  	; 05/11/2014
   343                                  	; 04/11/2014
   344                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   345                                  	;
   346                                  ;	xor	eax, eax
   347                                  ;	xor 	ecx, ecx
   348 0000032E B108                    	mov	cl, 8
   349 00000330 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   350 00000335 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   351                                  				   ; for the first 1 MB memory
   352                                  	;
   353 00000337 8B0D[60620000]          	mov	ecx, [mem_1m_1k]   ; 02/01/2022	
   354                                  	;mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   355                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   356                                  	;shr	cx, 2		   ; convert 1 KB count to 4 KB count
   357 0000033D C1E902                  	shr	ecx, 2	; 02/01/2022
   358 00000340 890D[E0640000]          	mov	[free_pages], ecx
   359 00000346 8B15[64620000]          	mov	edx, [mem_16m_64k] ; 02/01/2022
   360                                  	;mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   361                                  				   ; between 16 MB and 4 GB.
   362                                  	;or	dx, dx
   363 0000034C 09D2                    	or	edx, edx ; 02/01/2022
   364 0000034E 7412                    	jz	short mi_0
   365                                  	;
   366                                  	;mov	ax, dx
   367 00000350 89D0                    	mov	eax, edx ; 02/01/2022
   368 00000352 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   369 00000355 0105[E0640000]          	add	[free_pages], eax
   370 0000035B 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   371 00000360 EB06                    	jmp	short mi_1
   372                                  mi_0:
   373                                  	;mov	ax, cx
   374 00000362 89C8                    	mov	eax, ecx ; 02/01/2022	 
   375 00000364 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB
   376                                  mi_1:
   377 00000368 A3[DC640000]            	mov	[memory_size], eax ; Total available memory in pages
   378                                  				   ; 1 alloc. tbl. bit = 1 memory page
   379                                  				   ; 32 allocation bits = 32 mem. pages
   380                                  	;
   381 0000036D 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page
   382 00000372 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   383                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   384                                  				   ;  --> x M.A.T. pages, if y = 0
   385                                  	;mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages
   386 00000375 A3[F0640000]            	mov	[mat_size], eax ; 02/01/2022
   387 0000037A C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   388                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   389 0000037D 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   390                                  	; Set/Calculate Kernel's Page Directory Address
   391 0000037F 81C300001000            	add	ebx, MEM_ALLOC_TBL
   392 00000385 891D[D8640000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   393                                  				   ; just after the last M.A.T. page
   394                                  	;
   395 0000038B 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   396 0000038E A3[E8640000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   397                                  	;			   ; (allocation status search must be
   398                                  				   ; stopped after here)
   399 00000393 31C0                    	xor	eax, eax
   400 00000395 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)
   401                                  	;push	cx
   402 00000396 51                      	push	ecx ; 02/01/2022 
   403 00000397 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to
   404                                  				   ; count of 32 allocation bits
   405 0000039A F3AB                    	rep	stosd
   406                                  	;pop	cx
   407 0000039C 59                      	pop	ecx ; 02/01/2022
   408 0000039D 40                      	inc	eax		   ; 0
   409 0000039E 80E11F                  	and	cl, 31		   ; remain bits
   410 000003A1 7412                    	jz	short mi_4
   411 000003A3 8907                    	mov	[edi], eax	   ; reset
   412                                  mi_2:
   413 000003A5 0FAB07                  	bts	[edi], eax	   ; 06/11/2014
   414 000003A8 FEC9                    	dec	cl
   415 000003AA 7404                    	jz	short mi_3
   416 000003AC FEC0                    	inc	al
   417 000003AE EBF5                    	jmp	short mi_2
   418                                  mi_3:
   419 000003B0 28C0                    	sub	al, al	   	   ; 0
   420 000003B2 83C704                  	add	edi, 4		   ; 15/11/2014
   421                                  mi_4:
   422 000003B5 09D2                    	or	edx, edx ; 02/01/2022
   423                                  	;or	dx, dx		  ; check 16M to 4G memory space
   424 000003B7 741F                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   425                                  	;	
   426 000003B9 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   427                                  	;	
   428 000003BE 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   429 000003C0 7405                    	jz	short mi_5	  ; jump if EDI points to 
   430                                  				  ;         end of first 16 MB	
   431                                  	;shr	ecx, 1		  ; convert to dword count
   432                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   433 000003C2 C1E902                  	shr	ecx, 2	; 02/01/2022
   434 000003C5 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   435                                  				  ; (memory hole under 16 MB)
   436                                  mi_5:
   437 000003C7 89D1                    	mov	ecx, edx ; 02/01/2022
   438                                  	;mov	cx, dx		  ; count of 64 KB memory blocks
   439 000003C9 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   440 000003CB 9C                      	pushf			  ; 16/11/2014		
   441 000003CC 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   442 000003CD F3AB                    	rep	stosd
   443 000003CF 40                      	inc	eax		  ; 0
   444 000003D0 9D                      	popf			  ; 16/11/2014
   445 000003D1 7305                    	jnc	short mi_6
   446 000003D3 6648                    	dec	ax		  ; eax = 0000FFFFh
   447 000003D5 AB                      	stosd
   448 000003D6 6640                    	inc	ax		  ; 0		
   449                                  mi_6:
   450 000003D8 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   451 000003DA 7309                    	jnb	short mi_7	  ; end of memory allocation table
   452                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   453 000003DC 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   454 000003DE 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   455                                  	;shr	ecx, 1		  ; to dword count
   456                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   457 000003E0 C1E902                  	shr	ecx, 2 ; 02/01/2022	
   458 000003E3 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   459                                  mi_7:
   460                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   461 000003E5 BA00001000              	mov	edx, MEM_ALLOC_TBL
   462                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   463                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   464 000003EA 8B0D[F0640000]          	mov	ecx, [mat_size] ; 02/01/2022
   465                                  	;mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   466 000003F0 89D7                    	mov	edi, edx
   467 000003F2 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   468                                  				  ; byte offset in M.A.T.
   469                                  				  ; (1 M.A.T. byte points to 
   470                                  				  ;	      32768 bytes)
   471                                  				  ; Note: MEM_ALLOC_TBL address 
   472                                  				  ; must be aligned on 128 KB 
   473                                  				  ; boundary!
   474 000003F5 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   475                                  	; eax = 0
   476 000003F7 290D[E0640000]          	sub	[free_pages], ecx ; 07/11/2014
   477                                  mi_8:
   478 000003FD 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   479                                  	;dec	bl
   480 00000400 FEC9                    	dec	cl
   481 00000402 7404                    	jz	short mi_9
   482 00000404 FEC0                    	inc	al
   483 00000406 EBF5                    	jmp	short mi_8
   484                                  mi_9:
   485                                  	;
   486                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   487                                  	;		(allocate pages for system page tables)
   488                                  
   489                                  	; edx = MEM_ALLOC_TBL
   490 00000408 8B0D[DC640000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   491 0000040E 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)
   492 00000414 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   493                                  				 ; page table count (PDE count)
   494                                  	;
   495 00000417 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   496                                  	;
   497 00000418 41                      	inc	ecx		 ; +1 for kernel page directory	
   498                                  	;
   499 00000419 290D[E0640000]          	sub	[free_pages], ecx ; 07/11/2014
   500                                  	;
   501 0000041F 8B35[D8640000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   502 00000425 C1EE0C                  	shr	esi, 12		 ; convert to page number
   503                                  mi_10:
   504 00000428 89F0                    	mov	eax, esi	 ; allocation bit offset
   505 0000042A 89C3                    	mov	ebx, eax
   506 0000042C C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   507 0000042F 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   508                                  				 ;   to align on dword boundary
   509 00000432 83E01F                  	and	eax, 31		 ; set allocation bit position 
   510                                  				 ;  (bit 0 to bit 31)
   511                                  	;
   512 00000435 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   513                                  	;
   514 00000437 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   515                                  	;
   516 0000043A 46                      	inc	esi		 ; next page table
   517 0000043B E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   518                                  				 ; (ecx = page table count + 1)
   519                                  	;
   520 0000043D 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   521                                  	;
   522                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   523                                  	;
   524                                  	; Initialize Kernel's Page Directory
   525 0000043E 8B3D[D8640000]          	mov	edi, [k_page_dir]
   526 00000444 89F8                    	mov	eax, edi
   527 00000446 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   528                                  		     	      ; supervisor + read&write + present
   529 00000448 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)
   530                                  mi_11:
   531 0000044A 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   532                                  			        ; EAX points to next page table
   533 0000044F AB                      	stosd
   534 00000450 E2F8                    	loop	mi_11
   535 00000452 29C0                    	sub	eax, eax	; Empty PDE
   536                                  	;mov	cx, 1024	; Entry count (PGSZ/4)
   537                                  	; 02/01/2022
   538 00000454 B504                    	mov	ch, 4 ; cx = 4*256 = 1024
   539 00000456 29D1                    	sub	ecx, edx
   540 00000458 7402                    	jz	short mi_12
   541 0000045A F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   542                                  	;
   543                                  	; Initialization of Kernel's Page Directory is OK, here.
   544                                  mi_12:
   545                                  	; Initialize Kernel's Page Tables
   546                                  	;
   547                                  	; (EDI points to address of page table 0)
   548                                  	; eax = 0
   549 0000045C 8B0D[DC640000]          	mov	ecx, [memory_size] ; memory size in pages
   550 00000462 89CA                    	mov	edx, ecx	; (***)
   551 00000464 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   552                                  			     ; supervisor + read&write + present
   553                                  mi_13:
   554 00000466 AB                      	stosd
   555 00000467 0500100000              	add	eax, 4096	
   556 0000046C E2F8                    	loop	mi_13
   557                                  	; 02/01/2022
   558 0000046E 66B9FF03                	mov	cx, 1023
   559 00000472 21CA                    	and	edx, ecx
   560                                  	;and	dx, 1023	; (***)
   561 00000474 7407                    	jz	short mi_14
   562                                  	;mov	cx, 1024	
   563                                  	; 02/01/2022
   564                                  	;mov	ch, 4 ; cx = 4*256 = 1024
   565 00000476 41                      	inc	ecx ; ecx = 1024
   566 00000477 29D1                    	sub	ecx, edx
   567                                  	;sub	cx, dx		; from dx (<= 1023) to 1024
   568 00000479 31C0                    	xor	eax, eax
   569 0000047B F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   570                                  				; of the last page table
   571                                  mi_14:
   572                                  	;  Initialization of Kernel's Page Tables is OK, here.
   573                                  	;
   574 0000047D 89F8                    	mov	eax, edi	; end of the last page table page
   575                                  			        ; (beginging of user space pages)
   576 0000047F C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   577 00000482 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   578                                  				; aligning on dword boundary
   579                                  	 
   580 00000484 A3[EC640000]            	mov	[first_page], eax
   581 00000489 A3[E4640000]            	mov	[next_page], eax ; The first free page pointer
   582                                  				 ; for user programs
   583                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   584                                  	;
   585                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   586                                  	;
   587                                  	
   588                                  	; Enable paging
   589                                  	;
   590 0000048E A1[D8640000]                    mov     eax, [k_page_dir]
   591 00000493 0F22D8                  	mov	cr3, eax
   592 00000496 0F20C0                  	mov	eax, cr0
   593 00000499 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   594 0000049E 0F22C0                  	mov	cr0, eax
   595                                          ;jmp    KCODE:StartPMP
   596                                  
   597 000004A1 EA                      	db 0EAh 		; Opcode for far jump
   598 000004A2 [A8040000]                      dd StartPMP		; 32 bit offset
   599 000004A6 0800                    	dw KCODE		; kernel code segment descriptor
   600                                  
   601                                  StartPMP:
   602                                  	; 06/11//2014
   603                                  	; Clear video page 0
   604                                  	;
   605                                  	; Temporary Code
   606                                  	;
   607                                  	;mov	ecx, 80*25/2
   608 000004A8 66B9E803                	mov	cx, (80*25)/2 ; 02/01/2022
   609 000004AC BF00800B00              	mov	edi, 0B8000h
   610 000004B1 57                      	push	edi ; * ; 02/01/2022
   611 000004B2 31C0                    	xor	eax, eax	; black background, black fore color
   612 000004B4 F3AB                    	rep	stosd
   613                                  	
   614                                  	; 19/08/2014
   615                                  	; Kernel Base Address = 0
   616                                  	; It is mapped to (physically) 0 in the page table.
   617                                  	; So, here is exactly 'StartPMP' address.
   618                                  	;
   619                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   620                                  	;;mov	esi, msgPM
   621                                  	;; 14/08/2015 (kernel version message will appear
   622                                  	;;	       when protected mode and paging is enabled)
   623 000004B6 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   624 000004B8 BE[30600000]            	mov	esi, msgKVER
   625 000004BD 5F                      	pop	edi ; * ; 02/01/2022
   626                                  	;mov	edi, 0B8000h ; 27/08/2014
   627                                  	; 20/08/2014
   628 000004BE E892010000              	call	printk
   629                                  
   630                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   631                                  	; // Set IRQ offsets
   632                                  	;
   633                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   634                                  	;
   635                                  					;; ICW1
   636 000004C3 B011                    	mov	al, 11h			; Initialization sequence
   637 000004C5 E620                    	out	20h, al			; 	8259A-1
   638                                  	; jmp 	$+2
   639 000004C7 E6A0                    	out	0A0h, al		; 	8259A-2
   640                                  					;; ICW2
   641 000004C9 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   642 000004CB E621                    	out	21h, al			;	for 8259A-1
   643                                  	; jmp 	$+2
   644 000004CD B028                    	mov	al, 28h			; Start of hardware ints (28h)
   645 000004CF E6A1                    	out	0A1h, al		; 	for 8259A-2
   646                                  					;
   647 000004D1 B004                    	mov	al, 04h			;; ICW3
   648 000004D3 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   649                                  	; jmp 	$+2
   650 000004D5 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   651 000004D7 E6A1                    	out	0A1h, al		;
   652                                  					;; ICW4
   653 000004D9 B001                    	mov	al, 01h	 		;
   654 000004DB E621                    	out	21h, al			; 	8086 mode, normal EOI	
   655                                  	; jmp 	$+2
   656 000004DD E6A1                    	out	0A1h, al		;	for both chips.
   657                                  
   658                                  	;mov	al, 0FFh	; mask off all interrupts for now
   659                                  	;out	21h, al
   660                                  	;; jmp 	$+2
   661                                  	;out	0A1h, al
   662                                  
   663                                  	; 02/04/2015
   664                                  	; 26/03/2015 System call (INT 30h) modification
   665                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   666                                  	;
   667                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   668                                  	;  setup_idt:
   669                                  	;
   670                                          ;; 16/02/2015
   671                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   672                                  	; 21/08/2014 (timer_int)
   673 000004DF BE[FC5C0000]            	mov	esi, ilist
   674 000004E4 8D3D[70620000]          	lea	edi, [idt]
   675                                  	; 26/03/2015
   676 000004EA B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   677                                  	; 02/04/2015
   678 000004EF BB00000800              	mov	ebx,  80000h
   679                                  rp_sidt1:
   680 000004F4 AD                      	lodsd
   681 000004F5 89C2                    	mov	edx, eax
   682 000004F7 66BA008E                	mov	dx, 8E00h
   683 000004FB 6689C3                  	mov	bx, ax
   684 000004FE 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   685                                         			        ; /* interrupt gate - dpl=0, present */
   686 00000500 AB                      	stosd	; selector & offset bits 0-15 	
   687 00000501 89D0                    	mov	eax, edx
   688 00000503 AB                      	stosd	; attributes & offset bits 16-23
   689 00000504 E2EE                    	loop	rp_sidt1
   690 00000506 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   691                                  rp_sidt2:
   692 00000508 AD                      	lodsd
   693 00000509 21C0                    	and	eax, eax
   694 0000050B 7413                    	jz	short rp_sidt3
   695 0000050D 89C2                    	mov	edx, eax
   696 0000050F 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   697 00000513 6689C3                  	mov	bx, ax
   698 00000516 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   699 00000518 AB                      	stosd
   700 00000519 89D0                    	mov	eax, edx
   701 0000051B AB                      	stosd
   702 0000051C E2EA                    	loop	rp_sidt2
   703 0000051E EB16                    	jmp	short sidt_OK
   704                                  rp_sidt3:
   705 00000520 B8[79090000]            	mov	eax, ignore_int
   706 00000525 89C2                    	mov	edx, eax
   707 00000527 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   708 0000052B 6689C3                  	mov	bx, ax
   709 0000052E 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   710                                  rp_sidt4:
   711 00000530 AB                      	stosd
   712 00000531 92                      	xchg	eax, edx
   713 00000532 AB                      	stosd
   714 00000533 92                      	xchg	edx, eax
   715 00000534 E2FA                    	loop	rp_sidt4
   716                                  sidt_OK: 
   717 00000536 0F011D[F65C0000]        	lidt 	[idtd]
   718                                  	;
   719                                  	; TSS descriptor setup ; 24/03/2015
   720 0000053D B8[70640000]            	mov	eax, task_state_segment
   721 00000542 66A3[EA5C0000]          	mov	[gdt_tss0], ax
   722 00000548 C1C010                  	rol	eax, 16
   723 0000054B A2[EC5C0000]            	mov	[gdt_tss1], al
   724 00000550 8825[EF5C0000]          	mov	[gdt_tss2], ah
   725 00000556 66C705[D6640000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   725 0000055E 00                 
   726                                  		; 
   727                                  		; IO Map Base address (When this address points
   728                                  		; to end of the TSS, CPU does not use IO port 
   729                                  		; permission bit map for RING 3 IO permissions, 
   730                                  		; access to any IO ports in ring 3 will be forbidden.)
   731                                   		;
   732                                  	;mov	[tss.esp0], esp ; TSS offset 4
   733                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   734 0000055F 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   735                                  			 ; occurs (or a system call -software INT- is requested)
   736                                  			 ; while cpu running in ring 3 (in user mode).				
   737                                  			 ; (Kernel stack pointer and segment will be loaded
   738                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   739 00000563 0F00D8                  	ltr	ax  ; Load task register
   740                                  	;
   741                                  esp0_set0:
   742                                  	; 30/07/2015
   743 00000566 8B0D[DC640000]          	mov 	ecx, [memory_size] ; memory size in pages
   744 0000056C C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   745 0000056F 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   746                                  			  ; (kernel mode virtual address)
   747 00000575 7605                    	jna	short esp0_set1
   748                                  	;
   749                                  	; If available memory > CORE (end of the 1st 4 MB)
   750                                  	; set stack pointer to CORE
   751                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   752                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   753 00000577 B900004000              	mov	ecx, CORE
   754                                  esp0_set1:
   755 0000057C 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   756                                  esp0_set_ok:
   757                                  	; 30/07/2015 (**tss.esp0**) 
   758 0000057E 8925[74640000]          	mov	[tss.esp0], esp
   759 00000584 66C705[78640000]10-             mov     word [tss.ss0], KDATA
   759 0000058C 00                 
   760                                  	; 14/08/2015
   761                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   762                                  	;
   763                                  	;cli	; Disable interrupts (for CPU)
   764                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   765                                  	;
   766 0000058D 30C0                    	xor	al, al		; Enable all hardware interrupts!
   767 0000058F E621                    	out	21h, al		; (IBM PC-AT compatibility)
   768 00000591 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   769 00000593 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   770                                  				; (Even if related hardware component
   771                                  				;  does not exist!)
   772                                  	; Enable NMI 
   773 00000595 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   774 00000597 E670                    	out  	70h, al
   775                                  	; 23/02/2015
   776 00000599 90                      	nop
   777 0000059A E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   778                                  				; for preventing unknown state (!?)
   779                                  	;
   780                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   781                                  	;
   782                                  	; 02/09/2014
   783                                  	;xor	bx, bx
   784                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   785                                  	; 27/02/2022	
   786 0000059C 31DB                    	xor	ebx, ebx
   787 0000059E 31D2                    	xor	edx, edx
   788 000005A0 B602                    	mov	dh, 2
   789 000005A2 E8240F0000              	call	set_cpos
   790                                  	;
   791                                  	; 06/11/2014
   792                                  	; Temporary Code
   793                                  	;
   794 000005A7 E899100000              	call	memory_info
   795                                  	; 14/08/2015
   796                                  	;call getch ; 28/02/2015
   797                                  drv_init:
   798 000005AC FB                      	sti	; Enable Interrupts 
   799                                  	; 06/02/2015
   800 000005AD 8B15[D05F0000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   801 000005B3 668B1D[CE5F0000]        	mov	bx, [fd0_type] ; fd0, fd1
   802                                  	; 22/02/2015
   803 000005BA 6621DB                  	and	bx, bx
   804 000005BD 751B                    	jnz	short di1
   805                                  	;
   806 000005BF 09D2                    	or 	edx, edx
   807 000005C1 7529                    	jnz	short di2
   808                                  	;
   809                                  setup_error:
   810 000005C3 BE[19610000]            	mov 	esi, setup_error_msg
   811                                  psem:	
   812 000005C8 AC                      	lodsb
   813 000005C9 08C0                    	or	al, al
   814                                  	;jz	short haltx ; 22/02/2015
   815 000005CB 7426                    	jz	short di3
   816 000005CD 56                      	push	esi
   817 000005CE 31DB                    	xor	ebx, ebx ; 0
   818                                  			; Video page 0 (bl=0)
   819 000005D0 B407                    	mov	ah, 07h ; Black background, 
   820                                  			; light gray forecolor
   821 000005D2 E8EA0D0000              	call	write_tty
   822 000005D7 5E                      	pop	esi
   823 000005D8 EBEE                    	jmp	short psem
   824                                  
   825                                  di1:
   826                                  	; supress 'jmp short T6'
   827                                  	;  (activate fdc motor control code)
   828 000005DA 66C705[D6060000]90-     	mov	word [T5], 9090h ; nop
   828 000005E2 90                 
   829                                  	;
   830                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   831                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   832                                  	;stosw
   833                                  	;mov 	ax, cs
   834                                  	;stosw
   835                                  	;; 16/02/2015
   836                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   837                                  	;
   838 000005E3 E86E1A0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   839                                  	;
   840 000005E8 09D2                    	or	edx, edx
   841 000005EA 7407                            jz      short di3
   842                                  di2:
   843 000005EC E89F1A0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   844 000005F1 72D0                            jc      short setup_error
   845                                  di3:
   846 000005F3 E821100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   847                                  	;
   848 000005F8 E81E560000              	call	display_disks ; 07/03/2015  (Temporary)
   849                                  ;haltx:
   850                                  	; 14/08/2015
   851                                  	;call	getch ; 22/02/2015
   852 000005FD FB                      	sti	; Enable interrupts (for CPU)
   853                                  	; 14/08/2015
   854                                  	;mov 	ecx, 0FFFFFFFh
   855                                  	; 24/12/2021
   856 000005FE B9FFFF2F00              	mov 	ecx, 02FFFFFh
   857                                  md_info_msg_wait:
   858 00000603 51                      	push 	ecx
   859 00000604 B001                    	mov	al, 1
   860 00000606 8A25[06650000]          	mov 	ah, [ptty] ; active (current) video page
   861 0000060C E8F5520000              	call	getc_n
   862 00000611 59                      	pop	ecx
   863 00000612 7502                    	jnz	short md_info_msg_ok
   864 00000614 E2ED                    	loop	md_info_msg_wait
   865                                  md_info_msg_ok:
   866                                  	; 30/06/2015
   867 00000616 E8DF240000              	call	sys_init
   868                                  	;
   869                                  	;jmp 	cpu_reset ; 22/02/2015
   870                                  hang:
   871                                  	; 24/12/2021
   872 0000061B 29C0                    	sub	eax, eax
   873                                  _hang:	
   874                                  	; 23/02/2015
   875                                  	;sti			; Enable interrupts
   876 0000061D F4                      	hlt
   877                                  	;
   878                                  	;nop
   879                                  	;; 03/12/2014
   880                                  	;; 28/08/2014
   881                                  	;mov	ah, 11h
   882                                  	;call	getc
   883                                  	;jz      _c8
   884                                  	;
   885                                  	; 23/02/2015
   886                                  	; 06/02/2015
   887                                  	; 07/09/2014
   888 0000061E 31DB                    	xor	ebx, ebx
   889 00000620 8A1D[06650000]          	mov	bl, [ptty]	; active_page
   890 00000626 89DE                    	mov	esi, ebx
   891 00000628 66D1E6                  	shl 	si, 1
   892 0000062B 81C6[08650000]          	add	esi, ttychr
   893 00000631 668B06                  	mov	ax, [esi]
   894                                  	;and	ax, ax
   895                                  	;;jz	short _c8
   896                                  	;jz	short hang
   897                                  	; 24/12/2021
   898 00000634 21C0                    	and	eax, eax
   899 00000636 74E5                    	jz	short _hang
   900 00000638 66C7060000              	mov	word [esi], 0
   901 0000063D 80FB03                  	cmp	bl, 3		; Video page 3
   902                                  	;jb	short _c8
   903 00000640 72D9                    	jb	short hang
   904                                  	;	
   905                                  	; 02/09/2014
   906 00000642 B40E                    	mov	ah, 0Eh		; Yellow character 
   907                                  				; on black background
   908                                  	; 24/12/2021 (32 bit reg push-pop)
   909                                  	; 07/09/2014
   910                                  nxtl:
   911 00000644 53                      	push	ebx
   912                                  	;
   913                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   914                                  				; bh = 0 (video mode)
   915                                  				; Retro UNIX 386 v1 - Video Mode 0
   916                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   917 00000645 50                      	push	eax
   918 00000646 E8760D0000              	call 	write_tty
   919 0000064B 58                      	pop	eax
   920                                  	;pop	bx
   921 0000064C 5B                      	pop	ebx
   922 0000064D 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   923                                  	;jne	short _c8
   924 0000064F 75CA                    	jne	short hang
   925 00000651 B00A                    	mov	al, 0Ah		; next line
   926 00000653 EBEF                    	jmp	short nxtl
   927                                  	
   928                                  ;_c8:
   929                                  ;	; 25/08/2014
   930                                  ;	cli			; Disable interrupts
   931                                  ;	mov	al, [scounter + 1]
   932                                  ;	and	al, al
   933                                  ;	jnz	hang
   934                                  ;	call	rtc_p
   935                                  ;	jmp     hang
   936                                  
   937                                  
   938                                  	; 27/08/2014
   939                                  	; 20/08/2014
   940                                  printk:
   941                                          ;mov    edi, [scr_row]
   942                                  pkl:
   943 00000655 AC                      	lodsb
   944 00000656 08C0                    	or 	al, al
   945 00000658 7404                    	jz	short pkr
   946 0000065A 66AB                    	stosw
   947 0000065C EBF7                    	jmp	short pkl
   948                                  pkr:
   949 0000065E C3                      	retn
   950                                  
   951                                  ; 25/07/2015
   952                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   953                                  ; 17/02/2015
   954                                  ; 06/02/2015 (unix386.s)
   955                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   956                                  ;
   957                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   958                                  ;
   959                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   960                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   961                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   962                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   963                                  ;									       :
   964                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   965                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   966                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   967                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   968                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   969                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   970                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   971                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   972                                  ;-------------------------------------------------------------------------------
   973                                  ;
   974                                  
   975                                  timer_int:	; IRQ 0
   976                                  ;int_08h:	; Timer
   977                                  	; 14/10/2015
   978                                  	; Here, we are simulating system call entry (for task switch)
   979                                  	; (If multitasking is enabled, 
   980                                  	; 'clock' procedure may jump to 'sysrelease')
   981 0000065F 1E                      	push	ds
   982 00000660 06                      	push	es
   983 00000661 0FA0                    	push	fs
   984 00000663 0FA8                    	push	gs
   985 00000665 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   986 00000666 66B91000                	mov     cx, KDATA
   987 0000066A 8ED9                            mov     ds, cx
   988 0000066C 8EC1                            mov     es, cx
   989 0000066E 8EE1                            mov     fs, cx
   990 00000670 8EE9                            mov     gs, cx
   991                                  	;
   992 00000672 0F20D9                  	mov	ecx, cr3
   993 00000675 890D[18070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   994                                  	;
   995 0000067B 3B0D[D8640000]          	cmp 	ecx, [k_page_dir]
   996 00000681 741F                    	je	short T3
   997                                  	;
   998                                  	; timer interrupt has been occurred while OS is in user mode
   999 00000683 A3[98680000]            	mov 	[u.r0], eax
  1000 00000688 89E1                    	mov	ecx, esp
  1001 0000068A 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
  1002 0000068D 890D[90680000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
  1003 00000693 8925[94680000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
  1004                                  	;
  1005 00000699 8B0D[D8640000]          	mov	ecx, [k_page_dir]
  1006 0000069F 0F22D9                  	mov	cr3, ecx
  1007                                  T3:
  1008 000006A2 FB                      	sti				; INTERRUPTS BACK ON
  1009 000006A3 66FF05[54650000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
  1010 000006AA 7507                    	JNZ	short T4		; GO TO TEST_DAY
  1011 000006AC 66FF05[56650000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
  1012                                  T4:					; TEST_DAY
  1013 000006B3 66833D[56650000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
  1014 000006BB 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1015 000006BD 66813D[54650000]B0-     	CMP	word [TIMER_LOW],0B0H
  1015 000006C5 00                 
  1016 000006C6 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1017                                  
  1018                                  ;-----	TIMER HAS GONE 24 HOURS
  1019                                  	;;SUB	AX,AX
  1020                                  	;MOV	[TIMER_HIGH],AX
  1021                                  	;MOV	[TIMER_LOW],AX
  1022 000006C8 29C0                    	sub	eax, eax
  1023 000006CA A3[54650000]            	mov	[TIMER_LH], eax
  1024                                  	;	
  1025 000006CF C605[58650000]01        	MOV	byte [TIMER_OFL],1
  1026                                  
  1027                                  ;-----	TEST FOR DISKETTE TIME OUT
  1028                                  
  1029                                  T5:
  1030                                  	; 23/12/2014
  1031 000006D6 EB1D                    	jmp	short T6		; will be replaced with nop, nop
  1032                                  					; (9090h) if a floppy disk
  1033                                  					; is detected.
  1034                                  	;mov	al,[CS:MOTOR_COUNT]
  1035 000006D8 A0[5B650000]            	mov	al, [MOTOR_COUNT]
  1036 000006DD FEC8                    	dec	al
  1037                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1038 000006DF A2[5B650000]            	mov	[MOTOR_COUNT], al
  1039                                  	;mov	[ORG_MOTOR_COUNT], al
  1040 000006E4 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
  1041 000006E6 B0F0                    	mov 	al,0F0h
  1042                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
  1043 000006E8 2005[5A650000]          	and	[MOTOR_STATUS], al
  1044                                  	;and	[ORG_MOTOR_STATUS], al
  1045 000006EE B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
  1046                                  					; bit 2 = enable controller
  1047                                  					;	1 = normal operation
  1048                                  					;	0 = reset	
  1049                                  					; bit 0, 1 = drive select
  1050                                  					; bit 4-7 = motor running bits 
  1051 000006F0 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1052 000006F4 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1053                                  T6:	
  1054                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1055                                  					; TIMER TICK INTERRUPT
  1056                                  	;;inc	word [wait_count] ;;27/02/2015
  1057                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1058                                  	;;;;cli
  1059                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1060 000006F5 FF15[10070000]          	call	[x_timer] ; 14/05/2015
  1061                                  T7:
  1062                                  	; 14/10/2015
  1063 000006FB B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1064 000006FD FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1065 000006FE E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1066                                  	;
  1067 00000700 A1[18070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1068 00000705 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1069                                  	;
  1070 00000708 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1071                                  	;
  1072 00000709 0FA9                    	pop	gs
  1073 0000070B 0FA1                    	pop	fs
  1074 0000070D 07                      	pop	es
  1075 0000070E 1F                      	pop	ds
  1076 0000070F CF                      	iretd	; return from interrupt
  1077                                  
  1078                                  
  1079                                  ; ////////////////
  1080                                  
  1081                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1082                                  x_timer:
  1083 00000710 [1C070000]              	dd 	u_timer			; 14/05/2015
  1084                                  	;dd	clock
  1085                                  
  1086                                  ; 26/02/2022 - Real time clock (digital) output demo (sys emt)
  1087                                  x_rtci:
  1088 00000714 [520A0000]              	dd	rtc_p	; (temporary demo code)	; 26/02/2022
  1089                                  
  1090                                  ; 14/10/2015
  1091 00000718 00000000                cr3reg: dd 0
  1092                                  
  1093                                  	; 24/12/2021 - Retro UNIX 386 v1.1
  1094                                  	; 06/02/2015
  1095                                  	; 07/09/2014
  1096                                  	; 21/08/2014
  1097                                  u_timer:
  1098                                  ;timer_int:	; IRQ 0
  1099                                  	; 06/02/2015
  1100                                  	;push	eax
  1101                                  	;push	edx
  1102                                  	;push	ecx
  1103                                  	;push	ebx
  1104                                  	;push	ds
  1105                                  	;push	es
  1106                                  	;mov	eax, KDATA
  1107                                  	;mov	ds, ax
  1108                                  	;mov	es, ax
  1109 0000071C FF05[1C650000]          	inc	dword [tcount]
  1110 00000722 BB[A2600000]            	mov	ebx, tcountstr + 4
  1111                                  	;mov	ax, [tcount]
  1112                                  	; 24/12/2021
  1113 00000727 A1[1C650000]            	mov	eax, [tcount]
  1114 0000072C B90A000000              	mov	ecx, 10
  1115                                  rp_divtcnt:
  1116 00000731 31D2                    	xor	edx, edx
  1117 00000733 F7F1                    	div	ecx
  1118 00000735 80C230                  	add	dl, 30h
  1119 00000738 8813                    	mov	[ebx], dl
  1120                                  	;or	ax, ax
  1121                                  	; 24/12/2021
  1122 0000073A 09C0                    	or	eax, eax
  1123 0000073C 7403                    	jz	short print_lzero
  1124 0000073E 4B                      	dec	ebx
  1125 0000073F EBF0                    	jmp	short rp_divtcnt
  1126                                  print_lzero:
  1127 00000741 81FB[9E600000]          	cmp	ebx, tcountstr
  1128 00000747 7606                    	jna	short print_tcount
  1129 00000749 4B                      	dec	ebx
  1130 0000074A C60330                   	mov	byte [ebx], 30h
  1131 0000074D EBF2                    	jmp	short print_lzero
  1132                                  print_tcount:
  1133 0000074F 56                      	push	esi
  1134 00000750 57                      	push	edi
  1135 00000751 BE[7A600000]            	mov	esi, timer_msg ; Timer interrupt message
  1136                                  	; 07/09/2014
  1137                                  	;mov	bx, 1	; Video page 1
  1138                                  	; 24/12/2021
  1139 00000756 29DB                    	sub	ebx, ebx
  1140                                  	;inc	bl ; ebx = 1
  1141                                  	; 02/01/2022
  1142 00000758 B306                    	mov	bl, 6	; Video page 6
  1143                                  ptmsg:
  1144 0000075A AC                      	lodsb
  1145 0000075B 08C0                    	or	al, al
  1146 0000075D 740D                    	jz	short ptmsg_ok
  1147 0000075F 56                      	push	esi
  1148                                  	;push	bx
  1149                                  	; 24/12/2021
  1150 00000760 53                              push	ebx
  1151 00000761 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1152 00000763 E8590C0000              	call 	write_tty
  1153                                  	;pop	bx
  1154                                  	; 24/12/2021
  1155 00000768 5B                      	pop	ebx
  1156 00000769 5E                      	pop	esi
  1157 0000076A EBEE                    	jmp	short ptmsg
  1158                                  	;; 27/08/2014
  1159                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1160                                  	;call	printk
  1161                                  	;
  1162                                  ptmsg_ok:
  1163                                  	; 07/09/2014
  1164                                  	;xor	dx, dx		; column 0, row 0
  1165                                  	; 24/12/2021
  1166 0000076C 31D2                    	xor	edx, edx
  1167 0000076E E8580D0000              	call	set_cpos	; set cursor position to 0,0 
  1168                                  	; 23/02/2015
  1169                                  	; 25/08/2014
  1170                                  	;mov	ebx, scounter		; (seconds counter)
  1171                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1172                                  ;	dec	byte [scounter+1]
  1173                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1174                                  ;	jns	short u_timer_retn
  1175                                  	; 26/02/2015
  1176                                  ;	call	rtc_p
  1177                                  ;	mov	ebx, scounter		; (seconds counter)
  1178                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1179                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1180                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1181                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1182                                  ;	mov	byte [ebx], 5
  1183                                  ;	inc	byte [ebx+1] ; 19
  1184                                  ;;timer_eoi:
  1185                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1186                                  ;;	out	20h, al	; 8259 PORT
  1187                                  	;
  1188                                  ;u_timer_retn:  ; 06/02/2015
  1189 00000773 5F                      	pop	edi
  1190 00000774 5E                      	pop	esi
  1191                                  	;pop	es
  1192                                  	;pop	ds
  1193                                  	;pop	ebx
  1194                                  	;pop	ecx
  1195                                  	;pop	edx
  1196                                  	;pop	eax
  1197                                  	;iret
  1198 00000775 C3                      	retn	; 06/02/2015
  1199                                  
  1200                                  	; 28/08/2014
  1201                                  irq0:
  1202 00000776 6A00                            push 	dword 0
  1203 00000778 EB48                    	jmp	short which_irq
  1204                                  irq1:
  1205 0000077A 6A01                            push 	dword 1
  1206 0000077C EB44                    	jmp	short which_irq
  1207                                  irq2:
  1208 0000077E 6A02                            push 	dword 2
  1209 00000780 EB40                    	jmp	short which_irq
  1210                                  irq3:
  1211                                  	; 20/11/2015
  1212                                  	; 24/10/2015
  1213 00000782 2EFF15[15320000]        	call	dword [cs:com2_irq3]
  1214 00000789 6A03                    	push 	dword 3
  1215 0000078B EB35                    	jmp	short which_irq
  1216                                  irq4:
  1217                                  	; 20/11/2015
  1218                                  	; 24/10/2015
  1219 0000078D 2EFF15[11320000]        	call	dword [cs:com1_irq4]
  1220 00000794 6A04                            push 	dword 4
  1221 00000796 EB2A                    	jmp	short which_irq
  1222                                  irq5:
  1223 00000798 6A05                            push 	dword 5
  1224 0000079A EB26                    	jmp	short which_irq
  1225                                  irq6:
  1226 0000079C 6A06                            push 	dword 6
  1227 0000079E EB22                    	jmp	short which_irq
  1228                                  irq7:
  1229 000007A0 6A07                            push 	dword 7
  1230 000007A2 EB1E                    	jmp	short which_irq
  1231                                  irq8:
  1232 000007A4 6A08                            push 	dword 8
  1233 000007A6 EB1A                    	jmp	short which_irq
  1234                                  irq9:
  1235 000007A8 6A09                            push 	dword 9
  1236 000007AA EB16                    	jmp	short which_irq
  1237                                  irq10:
  1238 000007AC 6A0A                            push 	dword 10
  1239 000007AE EB12                    	jmp	short which_irq
  1240                                  irq11:
  1241 000007B0 6A0B                            push 	dword 11
  1242 000007B2 EB0E                    	jmp	short which_irq
  1243                                  irq12:
  1244 000007B4 6A0C                            push 	dword 12
  1245 000007B6 EB0A                    	jmp	short which_irq
  1246                                  irq13:
  1247 000007B8 6A0D                            push 	dword 13
  1248 000007BA EB06                    	jmp	short which_irq
  1249                                  irq14:
  1250 000007BC 6A0E                            push 	dword 14
  1251 000007BE EB02                    	jmp	short which_irq
  1252                                  irq15:
  1253 000007C0 6A0F                            push 	dword 15
  1254                                  	;jmp	short which_irq
  1255                                  
  1256                                  	; 19/10/2015
  1257                                  	; 29/08/2014
  1258                                  	; 21/08/2014
  1259                                  which_irq:
  1260 000007C2 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1261 000007C5 53                      	push	ebx
  1262 000007C6 56                      	push	esi
  1263 000007C7 57                      	push	edi
  1264 000007C8 1E                      	push 	ds
  1265 000007C9 06                      	push 	es
  1266                                  	;
  1267 000007CA 88C3                    	mov	bl, al
  1268                                  	;
  1269 000007CC B810000000              	mov	eax, KDATA
  1270 000007D1 8ED8                    	mov	ds, ax
  1271 000007D3 8EC0                    	mov	es, ax
  1272                                  	; 19/10/2015
  1273 000007D5 FC                      	cld
  1274                                          ; 27/08/2014
  1275 000007D6 8105[28600000]A000-             add     dword [scr_row], 0A0h
  1275 000007DE 0000               
  1276                                  	;
  1277 000007E0 B417                    	mov	ah, 17h	; blue (1) background, 
  1278                                  			; light gray (7) forecolor
  1279 000007E2 8B3D[28600000]                  mov     edi, [scr_row]
  1280 000007E8 B049                    	mov	al, 'I'
  1281 000007EA 66AB                    	stosw
  1282 000007EC B052                    	mov	al, 'R'
  1283 000007EE 66AB                    	stosw
  1284 000007F0 B051                    	mov	al, 'Q'
  1285 000007F2 66AB                    	stosw
  1286 000007F4 B020                    	mov	al, ' '
  1287 000007F6 66AB                    	stosw
  1288 000007F8 88D8                    	mov	al, bl
  1289 000007FA 3C0A                    	cmp	al, 10
  1290 000007FC 7208                    	jb	short iix
  1291 000007FE B031                    	mov	al, '1'
  1292 00000800 66AB                    	stosw
  1293 00000802 88D8                    	mov	al, bl
  1294 00000804 2C0A                    	sub	al, 10
  1295                                  iix:
  1296 00000806 0430                    	add	al, '0'
  1297 00000808 66AB                    	stosw
  1298 0000080A B020                    	mov	al, ' '
  1299 0000080C 66AB                    	stosw
  1300 0000080E B021                    	mov	al, '!'
  1301 00000810 66AB                    	stosw
  1302 00000812 B020                    	mov	al, ' '
  1303 00000814 66AB                    	stosw
  1304                                  	; 23/02/2015
  1305 00000816 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1306                                  	;jna	iiret
  1307                                  	; 02/01/2022
  1308 00000819 7604                    	jna	short iiz
  1309                                  iiy:
  1310 0000081B B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1311 0000081D E6A0                    	out	0A0h, al ; the 2nd 8259
  1312                                  iiz:
  1313 0000081F E983010000              	jmp     iiret
  1314                                  	;
  1315                                  	; 22/08/2014
  1316                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1317                                  	;out	20h, al	; 8259 PORT
  1318                                  	;
  1319                                  	;pop	es
  1320                                  	;pop	ds
  1321                                  	;pop	edi
  1322                                  	;pop	esi
  1323                                  	;pop	ebx
  1324                                  	;pop 	eax
  1325                                  	;iret
  1326                                  
  1327                                  	; 02/04/2015
  1328                                  	; 25/08/2014
  1329                                  exc0:
  1330 00000824 6A00                            push 	dword 0
  1331 00000826 E990000000                      jmp     cpu_except
  1332                                  exc1:
  1333 0000082B 6A01                            push 	dword 1
  1334 0000082D E989000000                      jmp     cpu_except
  1335                                  exc2:
  1336 00000832 6A02                            push 	dword 2
  1337 00000834 E982000000                      jmp     cpu_except
  1338                                  exc3:
  1339 00000839 6A03                            push 	dword 3
  1340 0000083B EB7E                            jmp     cpu_except
  1341                                  exc4:
  1342 0000083D 6A04                            push 	dword 4
  1343 0000083F EB7A                            jmp     cpu_except
  1344                                  exc5:
  1345 00000841 6A05                            push 	dword 5
  1346 00000843 EB76                            jmp     cpu_except
  1347                                  exc6:
  1348 00000845 6A06                            push 	dword 6
  1349 00000847 EB72                            jmp     cpu_except
  1350                                  exc7:
  1351 00000849 6A07                            push 	dword 7
  1352 0000084B EB6E                            jmp     cpu_except
  1353                                  exc8:
  1354                                  	; [esp] = Error code
  1355 0000084D 6A08                            push 	dword 8
  1356 0000084F EB5C                            jmp     cpu_except_en
  1357                                  exc9:
  1358 00000851 6A09                            push 	dword 9
  1359 00000853 EB66                            jmp     cpu_except
  1360                                  exc10:
  1361                                  	; [esp] = Error code
  1362 00000855 6A0A                            push 	dword 10
  1363 00000857 EB54                            jmp     cpu_except_en
  1364                                  exc11:
  1365                                  	; [esp] = Error code
  1366 00000859 6A0B                            push 	dword 11
  1367 0000085B EB50                            jmp     cpu_except_en
  1368                                  exc12:
  1369                                  	; [esp] = Error code
  1370 0000085D 6A0C                            push 	dword 12
  1371 0000085F EB4C                            jmp     cpu_except_en
  1372                                  exc13:
  1373                                  	; [esp] = Error code
  1374 00000861 6A0D                            push 	dword 13
  1375 00000863 EB48                            jmp     cpu_except_en
  1376                                  exc14:
  1377                                  	; [esp] = Error code
  1378 00000865 6A0E                            push 	dword 14
  1379 00000867 EB44                    	jmp	short cpu_except_en
  1380                                  exc15:
  1381 00000869 6A0F                            push 	dword 15
  1382 0000086B EB4E                            jmp     cpu_except
  1383                                  exc16:
  1384 0000086D 6A10                            push 	dword 16
  1385 0000086F EB4A                            jmp     cpu_except
  1386                                  exc17:
  1387                                  	; [esp] = Error code
  1388 00000871 6A11                            push 	dword 17
  1389 00000873 EB38                    	jmp	short cpu_except_en
  1390                                  exc18:
  1391 00000875 6A12                            push 	dword 18
  1392 00000877 EB42                    	jmp	short cpu_except
  1393                                  exc19:
  1394 00000879 6A13                            push 	dword 19
  1395 0000087B EB3E                    	jmp	short cpu_except
  1396                                  exc20:
  1397 0000087D 6A14                            push 	dword 20
  1398 0000087F EB3A                    	jmp	short cpu_except
  1399                                  exc21:
  1400 00000881 6A15                            push 	dword 21
  1401 00000883 EB36                    	jmp	short cpu_except
  1402                                  exc22:
  1403 00000885 6A16                            push 	dword 22
  1404 00000887 EB32                    	jmp	short cpu_except
  1405                                  exc23:
  1406 00000889 6A17                            push 	dword 23
  1407 0000088B EB2E                    	jmp	short cpu_except
  1408                                  exc24:
  1409 0000088D 6A18                            push 	dword 24
  1410 0000088F EB2A                    	jmp	short cpu_except
  1411                                  exc25:
  1412 00000891 6A19                            push 	dword 25
  1413 00000893 EB26                    	jmp	short cpu_except
  1414                                  exc26:
  1415 00000895 6A1A                            push 	dword 26
  1416 00000897 EB22                    	jmp	short cpu_except
  1417                                  exc27:
  1418 00000899 6A1B                            push 	dword 27
  1419 0000089B EB1E                    	jmp	short cpu_except
  1420                                  exc28:
  1421 0000089D 6A1C                            push 	dword 28
  1422 0000089F EB1A                    	jmp	short cpu_except
  1423                                  exc29:
  1424 000008A1 6A1D                            push 	dword 29
  1425 000008A3 EB16                    	jmp	short cpu_except
  1426                                  exc30:
  1427 000008A5 6A1E                            push 	dword 30
  1428 000008A7 EB04                    	jmp	short cpu_except_en
  1429                                  exc31:
  1430 000008A9 6A1F                            push 	dword 31
  1431 000008AB EB0E                            jmp     short cpu_except
  1432                                  
  1433                                  	; 02/01/2022
  1434                                  	; 19/10/2015
  1435                                  	; 19/09/2015
  1436                                  	; 01/09/2015
  1437                                  	; 28/08/2015
  1438                                  	; 28/08/2014
  1439                                  cpu_except_en:
  1440 000008AD 87442404                	xchg	eax, [esp+4] ; Error code
  1441 000008B1 36A3[84650000]          	mov	[ss:error_code], eax
  1442 000008B7 58                      	pop	eax  ; Exception number
  1443 000008B8 870424                  	xchg	eax, [esp]
  1444                                  		; eax = eax before exception
  1445                                  		; [esp] -> exception number
  1446                                  		; [esp+4] -> EIP to return
  1447                                  	; 19/10/2015
  1448                                  	; 19/09/2015
  1449                                  	; 01/09/2015
  1450                                  	; 28/08/2015
  1451                                  	; 29/08/2014
  1452                                  	; 28/08/2014
  1453                                  	; 25/08/2014
  1454                                  	; 21/08/2014
  1455                                  cpu_except:	; CPU Exceptions
  1456 000008BB FC                      	cld
  1457 000008BC 870424                  	xchg	eax, [esp] 
  1458                                  		; eax = Exception number
  1459                                  		; [esp] = eax (before exception)
  1460 000008BF 53                      	push	ebx
  1461 000008C0 56                      	push	esi
  1462 000008C1 57                      	push	edi
  1463 000008C2 1E                      	push 	ds
  1464 000008C3 06                      	push 	es
  1465                                  	; 28/08/2015
  1466 000008C4 66BB1000                	mov	bx, KDATA
  1467 000008C8 8EDB                    	mov	ds, bx
  1468 000008CA 8EC3                    	mov	es, bx
  1469 000008CC 0F20DB                  	mov	ebx, cr3
  1470 000008CF 53                      	push	ebx ; (*) page directory
  1471                                  	; 19/10/2015
  1472 000008D0 FC                      	cld
  1473                                  	; 25/03/2015
  1474 000008D1 8B1D[D8640000]          	mov	ebx, [k_page_dir]
  1475 000008D7 0F22DB                  	mov	cr3, ebx
  1476                                  	; 28/08/2015
  1477 000008DA 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1478 000008DD 7513                    	jne	short cpu_except_nfp
  1479 000008DF E8D01F0000              	call	page_fault_handler
  1480 000008E4 21C0                    	and 	eax, eax
  1481                                  	;jz	iiretp ; 01/09/2015
  1482                                  	; 02/01/2022
  1483 000008E6 7505                    	jnz	short cpu_except_pf
  1484 000008E8 E9B6000000              	jmp	iiretp
  1485                                  cpu_except_pf:
  1486 000008ED B80E000000              	mov	eax, 0Eh ; 14
  1487                                  cpu_except_nfp:
  1488                                  	; 02/04/2015
  1489 000008F2 BB[1B060000]            	mov	ebx, hang
  1490 000008F7 875C241C                	xchg	ebx, [esp+28]
  1491                                  		; EIP (points to instruction which faults)
  1492                                  	  	; New EIP (hang)
  1493 000008FB 891D[88650000]          	mov	[FaultOffset], ebx
  1494 00000901 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1495 00000909 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1496                                  	;
  1497 00000911 88C4                    	mov	ah, al
  1498 00000913 240F                    	and	al, 0Fh
  1499 00000915 3C09                    	cmp	al, 9
  1500 00000917 7602                    	jna	short h1ok
  1501 00000919 0407                    	add	al, 'A'-':'
  1502                                  h1ok:
  1503 0000091B D0EC                    	shr	ah, 1
  1504 0000091D D0EC                    	shr	ah, 1
  1505 0000091F D0EC                    	shr	ah, 1
  1506 00000921 D0EC                    	shr	ah, 1
  1507 00000923 80FC09                  	cmp	ah, 9
  1508 00000926 7603                    	jna	short h2ok
  1509 00000928 80C407                  	add	ah, 'A'-':'
  1510                                  h2ok:	
  1511 0000092B 86E0                    	xchg 	ah, al	
  1512 0000092D 66053030                	add	ax, '00'
  1513 00000931 66A3[B6600000]          	mov	[excnstr], ax
  1514                                  	;
  1515                                  	; 29/08/2014
  1516 00000937 A1[88650000]            	mov	eax, [FaultOffset]
  1517 0000093C 51                      	push	ecx
  1518 0000093D 52                      	push	edx
  1519 0000093E 89E3                    	mov	ebx, esp
  1520                                  	; 28/08/2015
  1521 00000940 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1522                                  			  ; to hexadecimal string
  1523                                  	;mov	ecx, 10	    ; divisor to convert
  1524                                  			    ; binary number to decimal string
  1525                                  b2d1:
  1526 00000945 31D2                    	xor	edx, edx
  1527 00000947 F7F1                    	div	ecx
  1528                                  	;push	dx
  1529                                  	; 02/01/2022
  1530 00000949 52                      	push	edx
  1531 0000094A 39C8                    	cmp	eax, ecx
  1532 0000094C 73F7                    	jnb	short b2d1
  1533 0000094E BF[C1600000]            	mov	edi, EIPstr ; EIP value
  1534                                  			    ; points to instruction which faults
  1535                                  	; 28/08/2015
  1536 00000953 89C2                    	mov	edx, eax
  1537                                  b2d2:
  1538                                  	;add	al, '0'
  1539 00000955 8A82[FD160000]          	mov	al, [edx+hexchrs]
  1540 0000095B AA                      	stosb		    ; write hexadecimal digit to its place
  1541 0000095C 39E3                    	cmp	ebx, esp
  1542 0000095E 7605                    	jna	short b2d3
  1543                                  	; 02/01/2022
  1544 00000960 58                      	pop	eax
  1545                                  	;pop	ax
  1546 00000961 88C2                    	mov	dl, al
  1547 00000963 EBF0                    	jmp	short b2d2
  1548                                  b2d3:
  1549 00000965 B068                    	mov 	al, 'h' ; 28/08/2015
  1550 00000967 AA                      	stosb
  1551 00000968 B020                    	mov	al, 20h	    ; space
  1552 0000096A AA                      	stosb
  1553 0000096B 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1554 0000096D AA                      	stosb
  1555                                  	;
  1556 0000096E 5A                      	pop	edx
  1557 0000096F 59                      	pop	ecx
  1558                                  	;
  1559 00000970 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1560                                  			; white (F) forecolor
  1561 00000972 BE[A6600000]            	mov	esi, exc_msg ; message offset
  1562                                  	;
  1563 00000977 EB11                    	jmp	short piemsg
  1564                                  	;
  1565                                          ;add    dword [scr_row], 0A0h
  1566                                          ;mov    edi, [scr_row]
  1567                                          ;
  1568                                  	;call 	printk
  1569                                  	;
  1570                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1571                                  	;out	20h, al	; 8259 PORT
  1572                                  	;
  1573                                  	;pop	es
  1574                                  	;pop	ds
  1575                                  	;pop	edi
  1576                                  	;pop	esi
  1577                                  	;pop 	eax
  1578                                  	;iret
  1579                                  	
  1580                                  	; 28/08/2015
  1581                                  	; 23/02/2015
  1582                                  	; 20/08/2014
  1583                                  ignore_int:
  1584 00000979 50                      	push	eax
  1585 0000097A 53                      	push	ebx ; 23/02/2015
  1586 0000097B 56                      	push	esi
  1587 0000097C 57                      	push	edi
  1588 0000097D 1E                      	push 	ds
  1589 0000097E 06                      	push 	es
  1590                                  	; 28/08/2015
  1591 0000097F 0F20D8                  	mov	eax, cr3
  1592 00000982 50                      	push	eax ; (*) page directory
  1593                                  	;
  1594 00000983 B467                    	mov	ah, 67h	; brown (6) background, 
  1595                                  			; light gray (7) forecolor
  1596 00000985 BE[64600000]            	mov	esi, int_msg ; message offset
  1597                                  piemsg:
  1598                                          ; 27/08/2014
  1599 0000098A 8105[28600000]A000-             add     dword [scr_row], 0A0h
  1599 00000992 0000               
  1600 00000994 8B3D[28600000]                  mov     edi, [scr_row]
  1601                                          ;
  1602 0000099A E8B6FCFFFF              	call 	printk
  1603                                  	;
  1604                                  	; 23/02/2015
  1605 0000099F B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1606 000009A1 E6A0                    	out	0A0h, al ; the 2nd 8259
  1607                                  iiretp: ; 01/09/2015
  1608                                  	; 28/08/2015
  1609 000009A3 58                      	pop	eax ; (*) page directory
  1610 000009A4 0F22D8                  	mov	cr3, eax
  1611                                  	;
  1612                                  iiret:
  1613                                  	; 22/08/2014
  1614 000009A7 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1615 000009A9 E620                    	out	20h, al	; 8259 PORT
  1616                                  	;
  1617 000009AB 07                      	pop	es
  1618 000009AC 1F                      	pop	ds
  1619 000009AD 5F                      	pop	edi
  1620 000009AE 5E                      	pop	esi
  1621 000009AF 5B                      	pop	ebx ; 29/08/2014
  1622 000009B0 58                      	pop 	eax
  1623 000009B1 CF                      	iretd
  1624                                  
  1625                                  	; 26/02/2022
  1626                                  	; 26/02/2015
  1627                                  	; 07/09/2014
  1628                                  	; 25/08/2014
  1629                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1630                                  	; 22/08/2014
  1631 000009B2 50                      	push	eax
  1632 000009B3 53                      	push	ebx ; 29/08/2014
  1633 000009B4 56                      	push	esi
  1634 000009B5 57                      	push	edi
  1635 000009B6 1E                      	push 	ds
  1636 000009B7 06                      	push 	es
  1637                                  	;
  1638 000009B8 B810000000              	mov	eax, KDATA
  1639 000009BD 8ED8                    	mov	ds, ax
  1640 000009BF 8EC0                    	mov	es, ax
  1641                                  	;
  1642                                  	; 25/08/2014
  1643                                  	;call	rtc_p
  1644                                  	; 26/02/2022
  1645 000009C1 FF15[14070000]          	call	[x_rtci]
  1646                                  	;
  1647                                  	; 22/02/2015 - dsectpm.s
  1648                                  	; [ source: http://wiki.osdev.org/RTC ]
  1649                                  	; read status register C to complete procedure
  1650                                  	;(it is needed to get a next IRQ 8) 
  1651 000009C7 B00C                    	mov	al, 0Ch ; 
  1652 000009C9 E670                    	out	70h, al ; select register C
  1653 000009CB 90                      	nop
  1654 000009CC E471                    	in	al, 71h ; just throw away contents
  1655                                  	; 22/02/2015
  1656 000009CE B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1657 000009D0 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1658                                  	;
  1659 000009D2 EBD3                    	jmp	short iiret	
  1660                                  
  1661                                  	; 22/08/2014
  1662                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1663                                  	; (INT 1Ah)
  1664                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1665                                  time_of_day:
  1666 000009D4 E866010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1667 000009D9 726F                            jc      short rtc_retn 
  1668 000009DB B000                    	mov	al, CMOS_SECONDS
  1669 000009DD E847010000              	call	CMOS_READ
  1670 000009E2 A2[4C650000]            	mov	[time_seconds], al 
  1671 000009E7 B002                    	mov	al, CMOS_MINUTES
  1672 000009E9 E83B010000              	call	CMOS_READ
  1673 000009EE A2[4D650000]            	mov	[time_minutes], al 
  1674 000009F3 B004                    	mov	al, CMOS_HOURS
  1675 000009F5 E82F010000              	call	CMOS_READ
  1676 000009FA A2[4E650000]                    mov     [time_hours], al
  1677 000009FF B006                    	mov	al, CMOS_DAY_WEEK 
  1678 00000A01 E823010000              	call	CMOS_READ
  1679 00000A06 A2[4F650000]            	mov	[date_wday], al
  1680 00000A0B B007                     	mov	al, CMOS_DAY_MONTH
  1681 00000A0D E817010000              	call	CMOS_READ
  1682 00000A12 A2[50650000]            	mov	[date_day], al
  1683 00000A17 B008                    	mov	al, CMOS_MONTH
  1684 00000A19 E80B010000              	call	CMOS_READ
  1685 00000A1E A2[51650000]            	mov	[date_month], al
  1686 00000A23 B009                    	mov	al, CMOS_YEAR
  1687 00000A25 E8FF000000              	call	CMOS_READ
  1688 00000A2A A2[52650000]            	mov	[date_year], al
  1689 00000A2F B032                    	mov	al, CMOS_CENTURY
  1690 00000A31 E8F3000000              	call	CMOS_READ
  1691 00000A36 A2[53650000]            	mov	[date_century], al
  1692                                  	;
  1693 00000A3B B000                    	mov	al, CMOS_SECONDS
  1694 00000A3D E8E7000000              	call 	CMOS_READ
  1695 00000A42 3A05[4C650000]          	cmp	al, [time_seconds]
  1696 00000A48 758A                    	jne	short time_of_day
  1697                                  
  1698                                  rtc_retn:
  1699 00000A4A C3                      	retn
  1700                                  
  1701                                  rtci_default:
  1702                                  	; 26/02/2022 (Temporary!)
  1703                                  	; (default real time clock handler in multitasking mode)
  1704                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1705 00000A4B FF05[90650000]          	inc	dword [rtc_ticks] ; real time clock counter
  1706                                  			; (not used in anywhere of kernel for now!)
  1707 00000A51 C3                      	retn
  1708                                  
  1709                                  rtc_p:	
  1710                                  	; 07/09/2014
  1711                                  	; 29/08/2014
  1712                                  	; 27/08/2014
  1713                                  	; 25/08/2014
  1714                                   	; Print Real Time Clock content
  1715                                  	;
  1716                                  	;
  1717 00000A52 E87DFFFFFF              	call	time_of_day
  1718 00000A57 72F1                    	jc	short rtc_retn
  1719                                  	;
  1720 00000A59 3A05[18610000]          	cmp	al, [ptime_seconds]
  1721 00000A5F 74E9                            je      short rtc_retn ; 29/08/2014
  1722                                  	;
  1723 00000A61 A2[18610000]            	mov	[ptime_seconds], al
  1724                                  	;
  1725 00000A66 A0[53650000]            	mov	al, [date_century]
  1726 00000A6B E8EA000000              	call	bcd_to_ascii
  1727 00000A70 66A3[E5600000]          	mov	[datestr+6], ax
  1728 00000A76 A0[52650000]            	mov	al, [date_year]
  1729 00000A7B E8DA000000              	call	bcd_to_ascii
  1730 00000A80 66A3[E7600000]          	mov	[datestr+8], ax
  1731 00000A86 A0[51650000]            	mov	al, [date_month]
  1732 00000A8B E8CA000000              	call	bcd_to_ascii
  1733 00000A90 66A3[E2600000]          	mov	[datestr+3], ax
  1734 00000A96 A0[50650000]            	mov	al, [date_day]
  1735 00000A9B E8BA000000              	call	bcd_to_ascii
  1736 00000AA0 66A3[DF600000]          	mov	[datestr], ax
  1737                                  	;
  1738 00000AA6 0FB61D[4F650000]        	movzx	ebx, byte [date_wday]
  1739 00000AAD C0E302                  	shl 	bl, 2
  1740 00000AB0 81C3[F8600000]          	add	ebx, daytmp
  1741 00000AB6 8B03                    	mov	eax, [ebx]
  1742 00000AB8 A3[EA600000]            	mov	[daystr], eax
  1743                                  	;
  1744 00000ABD A0[4E650000]            	mov	al, [time_hours]
  1745 00000AC2 E893000000              	call	bcd_to_ascii
  1746 00000AC7 66A3[EE600000]          	mov	[timestr], ax
  1747 00000ACD A0[4D650000]            	mov	al, [time_minutes]
  1748 00000AD2 E883000000              	call	bcd_to_ascii
  1749 00000AD7 66A3[F1600000]          	mov	[timestr+3], ax
  1750 00000ADD A0[4C650000]            	mov	al, [time_seconds]
  1751 00000AE2 E873000000              	call	bcd_to_ascii
  1752 00000AE7 66A3[F4600000]          	mov	[timestr+6], ax
  1753                                  	;		
  1754 00000AED BE[CD600000]            	mov	esi, rtc_msg ; message offset
  1755                                  	; 23/02/2015
  1756 00000AF2 52                      	push	edx
  1757 00000AF3 51                      	push	ecx
  1758                                  	; 07/09/2014
  1759                                  	;mov	bx, 2	; Video page 2
  1760                                  	; 02/01/2022
  1761 00000AF4 29DB                    	sub	ebx, ebx
  1762 00000AF6 B307                    	mov	bl, 7	; Video page 7 
  1763                                  prtmsg:
  1764 00000AF8 AC                      	lodsb
  1765 00000AF9 08C0                    	or	al, al
  1766 00000AFB 740D                    	jz	short prtmsg_ok
  1767 00000AFD 56                      	push	esi
  1768                                  	; 02/01/2022
  1769 00000AFE 53                      	push	ebx
  1770                                  	;push	bx
  1771 00000AFF B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1772                                  			; white (F) forecolor
  1773 00000B01 E8BB080000              	call 	write_tty
  1774                                  	;pop	bx
  1775                                  	; 02/01/2022
  1776 00000B06 5B                      	pop	ebx
  1777 00000B07 5E                      	pop	esi
  1778 00000B08 EBEE                    	jmp	short prtmsg
  1779                                  	;
  1780                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1781                                  	;call	printk
  1782                                  prtmsg_ok:
  1783                                  	; 07/09/2014
  1784                                  	;xor	dx, dx		; column 0, row 0
  1785                                  	; 02/01/2022
  1786 00000B0A 31D2                    	xor	edx, edx
  1787 00000B0C E8BA090000              	call	set_cpos	; set curspor position to 0,0 
  1788                                  	; 23/02/2015
  1789 00000B11 59                      	pop	ecx
  1790 00000B12 5A                      	pop	edx
  1791 00000B13 C3                      	retn
  1792                                  
  1793                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1794                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1795                                  default_irq7:
  1796                                  	; 24/12/2021
  1797                                  	;push	ax
  1798 00000B14 50                      	push	eax
  1799 00000B15 B00B                    	mov	al, 0Bh  ; In-Service register
  1800 00000B17 E620                    	out	20h, al
  1801 00000B19 EB00                            jmp short $+2
  1802 00000B1B EB00                    	jmp short $+2
  1803 00000B1D E420                    	in	al, 20h
  1804 00000B1F 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1805 00000B21 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1806 00000B23 B020                            mov     al, 20h ; EOI
  1807 00000B25 E620                    	out	20h, al 
  1808                                  irq7_iret:
  1809                                  	;pop	ax
  1810                                  	; 24/12/2021
  1811 00000B27 58                      	pop	eax
  1812 00000B28 CF                      	iretd	
  1813                                  	
  1814                                  	; 24/12/2021
  1815                                  	; 22/08/2014
  1816                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1817                                  CMOS_READ:
  1818 00000B29 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1819 00000B2A D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1820 00000B2C F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1821 00000B2D D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1822 00000B2F FA                      	cli		; DISABLE INTERRUPTS
  1823 00000B30 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1824 00000B32 90                      	nop		; I/O DELAY
  1825 00000B33 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1826                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1827                                  	; 24/12/2021
  1828 00000B35 50                      	push	eax
  1829                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1830                                  		     ; ----- 10/06/85 (test4.asm)
  1831 00000B36 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1832                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1833 00000B38 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1834 00000B3A E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1835                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1836                                  	; 24/12/2021
  1837 00000B3C 58                      	pop	eax
  1838 00000B3D 9D                      	popf	
  1839 00000B3E C3                      	retn		; RETURN WITH FLAGS RESTORED
  1840                                  
  1841                                  	; 22/08/2014
  1842                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1843                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1844 00000B3F 51                      	push	ecx
  1845 00000B40 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1846                                  		; mov cx, 800	
  1847                                  UPD_10:
  1848 00000B45 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1849 00000B47 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1850 00000B48 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1851 00000B4D A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1852 00000B4F 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1853 00000B51 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1854 00000B52 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1855 00000B54 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1856                                  		; xor ax, ax
  1857 00000B56 F9                      	stc				; SET CARRY FOR ERROR
  1858                                  UPD_90:
  1859 00000B57 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1860 00000B58 FA                      	cli				; INTERRUPTS OFF DURING SET
  1861 00000B59 C3                      	retn				; RETURN WITH CY FLAG SET
  1862                                  
  1863                                  bcd_to_ascii:
  1864                                  	; 25/08/2014
  1865                                  	; INPUT ->
  1866                                  	;	al = Packed BCD number
  1867                                  	; OUTPUT ->
  1868                                  	;	ax  = ASCII word/number
  1869                                  	;
  1870                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1871                                  	;
  1872 00000B5A D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1873                                  					; AH = AL / 10h
  1874                                  					; AL = AL MOD 10h
  1875 00000B5C 660D3030                	or ax,'00'                      ; Make it ASCII based
  1876                                  
  1877 00000B60 86E0                            xchg ah, al 
  1878                                  	
  1879 00000B62 C3                      	retn	
  1880                                  	
  1881                                  
  1882                                  %include 'keyboard.inc' ; 07/03/2015
  1883                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - KEYBOARD.INC
  1884                              <1> ; Last Modification: 13/06/2022
  1885                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1886                              <1> ;
  1887                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1888                              <1> 
  1889                              <1> ; 23/02/2022
  1890                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1891                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1892                              <1> ; 30/06/2015
  1893                              <1> ; 11/03/2015
  1894                              <1> ; 28/02/2015
  1895                              <1> ; 25/02/2015
  1896                              <1> ; 20/02/2015
  1897                              <1> ; 18/02/2015
  1898                              <1> ; 03/12/2014
  1899                              <1> ; 07/09/2014
  1900                              <1> ; KEYBOARD INTERRUPT HANDLER
  1901                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1902                              <1> 
  1903                              <1> ;getch:
  1904                              <1> ;	; 18/02/2015
  1905                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1906                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1907                              <1> ;	; routine, later... (multi tasking ability)
  1908                              <1> ;	; 28/02/2015
  1909                              <1> ;	sti	; enable interrupts
  1910                              <1> ;	;
  1911                              <1> ;	;push	esi
  1912                              <1> ;	;push	ebx
  1913                              <1> ;	;xor	ebx, ebx
  1914                              <1> ;	;mov	bl, [ptty]  ; active_page
  1915                              <1> ;	;mov	esi, ebx
  1916                              <1> ;	;shl 	si, 1
  1917                              <1> ;	;add	esi, ttychr
  1918                              <1> ;getch_1:
  1919                              <1> ;	;mov	ax, [esi]
  1920                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1921                              <1> ;	and	ax, ax
  1922                              <1> ;	jz	short getch_2
  1923                              <1> ;	mov	word [ttychr], 0
  1924                              <1> ;	;mov	word [esi], 0
  1925                              <1> ;	;pop	ebx
  1926                              <1> ;	;pop	esi
  1927                              <1> ;	retn
  1928                              <1> ;getch_2:
  1929                              <1> ;	hlt	; not proper for multi tasking!
  1930                              <1> ;		; (temporary halt for now)
  1931                              <1> ;		; 'sleep' on tty 
  1932                              <1> ;		; will (must) be located here		
  1933                              <1> ;	nop
  1934                              <1> ;	jmp	short getch_1
  1935                              <1> 
  1936                              <1> keyb_int:
  1937                              <1> 	; 23/02/2022
  1938                              <1> 	; 30/06/2015
  1939                              <1> 	; 25/02/2015
  1940                              <1> 	; 20/02/2015
  1941                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1942                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1943                              <1> 	; 30/06/2014
  1944                              <1> 	; 10/05/2013	
  1945                              <1>       	; Retro Unix 8086 v1 feature only!
  1946                              <1> 	; 03/03/2014
  1947                              <1> 	
  1948 00000B63 1E                  <1> 	push	ds
  1949 00000B64 53                  <1> 	push	ebx
  1950 00000B65 50                  <1> 	push	eax
  1951                              <1> 	;
  1952                              <1> 	; 23/02/2022
  1953 00000B66 9C                  <1> 	pushfd
  1954 00000B67 0E                  <1> 	push	cs
  1955                              <1> 	;mov	ax, KDATA
  1956 00000B68 31C0                <1> 	xor	eax, eax
  1957 00000B6A B010                <1> 	mov	al, KDATA
  1958 00000B6C 8ED8                <1> 	mov	ds, ax
  1959                              <1> 	;
  1960                              <1> 	;pushfd
  1961                              <1> 	;push	cs
  1962 00000B6E E810020000          <1> 	call	kb_int   ; int_09h
  1963                              <1> 	;
  1964 00000B73 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1965                              <1> 	;call	getc
  1966 00000B75 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1967 00000B7A 744E                <1> 	jz	short keyb_int4
  1968                              <1> 	;
  1969 00000B7C B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1970                              <1> 	;call	getc
  1971 00000B7E E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1972                              <1> 	;
  1973                              <1> 	; 20/02/2015
  1974 00000B83 0FB61D[06650000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1975                              <1> 	;
  1976 00000B8A 20C0                <1> 	and 	al, al
  1977 00000B8C 751D                <1> 	jnz	short keyb_int1
  1978                              <1> 	;
  1979 00000B8E 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1980 00000B91 7218                <1> 	jb	short keyb_int1
  1981 00000B93 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1982 00000B96 7713                <1> 	ja	short keyb_int1
  1983                              <1> 	;
  1984 00000B98 88D8                <1> 	mov	al, bl
  1985 00000B9A 0468                <1> 	add	al, 68h
  1986 00000B9C 38E0                <1> 	cmp	al, ah
  1987 00000B9E 7409                <1> 	je	short keyb_int0
  1988 00000BA0 88E0                <1> 	mov	al, ah
  1989 00000BA2 2C68                <1> 	sub	al, 68h
  1990 00000BA4 E8370A0000          <1> 	call	tty_sw
  1991                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1992                              <1> keyb_int0: ; 30/06/2015
  1993                              <1> 	;xor	ax, ax
  1994                              <1> 	; 23/02/2022
  1995 00000BA9 31C0                <1> 	xor	eax, eax
  1996                              <1> keyb_int1:
  1997 00000BAB D0E3                <1> 	shl	bl, 1
  1998 00000BAD 81C3[08650000]      <1> 	add	ebx, ttychr
  1999                              <1> 	;
  2000                              <1> 	;23/02/2022
  2001 00000BB3 09C0                <1> 	or	eax, eax
  2002                              <1> 	;or	ax, ax
  2003 00000BB5 7406                <1> 	jz	short keyb_int2
  2004                              <1> 	;
  2005 00000BB7 66833B00            <1> 	cmp 	word [ebx], 0
  2006 00000BBB 7703                <1>         ja      short keyb_int3 
  2007                              <1> keyb_int2:
  2008 00000BBD 668903              <1>         mov	[ebx], ax  ; Save ascii code
  2009                              <1> 			   ; and scan code of the character
  2010                              <1> 			   ; for current tty (or last tty
  2011                              <1> 			   ; just before tty switch).
  2012                              <1> keyb_int3:
  2013 00000BC0 A0[06650000]        <1>         mov     al, [ptty]
  2014 00000BC5 E8563C0000          <1> 	call	wakeup
  2015                              <1> 	;
  2016                              <1> keyb_int4:
  2017 00000BCA 58                  <1> 	pop	eax
  2018 00000BCB 5B                  <1> 	pop	ebx
  2019 00000BCC 1F                  <1> 	pop	ds
  2020 00000BCD CF                  <1> 	iret
  2021                              <1> 
  2022                              <1> ; 18/02/2015
  2023                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  2024                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  2025                              <1> ; scancode and ascii code of the character 
  2026                              <1> ; in the tty input (ttychr) buffer. 
  2027                              <1> ; Test procedures must call 'getch' for tty input
  2028                              <1> ; otherwise, 'getc' will not be able to return to the caller
  2029                              <1> ; due to infinite (key press) waiting loop.
  2030                              <1> ; 
  2031                              <1> ; 03/12/2014
  2032                              <1> ; 26/08/2014
  2033                              <1> ; KEYBOARD I/O
  2034                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  2035                              <1> 
  2036                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  2037                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2038                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2039                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2040                              <1> 
  2041                              <1> int_16h: ; 30/06/2015
  2042                              <1> ;getc:
  2043 00000BCE 9C                  <1> 	pushfd	; 28/08/2014
  2044 00000BCF 0E                  <1> 	push 	cs
  2045 00000BD0 E826000000          <1> 	call 	getc_int
  2046 00000BD5 C3                  <1> 	retn
  2047                              <1> 
  2048                              <1> ; 24/12/2021
  2049                              <1> 
  2050                              <1> 	;-----	SHIFT STATUS
  2051                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2052 00000BD6 8A25[045F0000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2053 00000BDC 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2054                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2055                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2056 00000BDF C0E405              <1>         shl	ah, 5
  2057 00000BE2 A0[045F0000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2058 00000BE7 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2059 00000BE9 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2060 00000BEB A0[065F0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2061 00000BF0 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2062 00000BF2 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2063                              <1> _K3:
  2064 00000BF4 A0[035F0000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2065 00000BF9 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2066                              <1> 
  2067                              <1> getc_int:
  2068                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2069                              <1> 	; 28/02/2015
  2070                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2071                              <1> 	;	      instead of pc-at bios - 1985-)
  2072                              <1> 	; 28/08/2014 (_k1d)
  2073                              <1> 	; 30/06/2014
  2074                              <1> 	; 03/03/2014
  2075                              <1> 	; 28/02/2014
  2076                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2077                              <1> 	; rombios source code (21/04/1986)
  2078                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2079                              <1> 	;
  2080                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2081                              <1> 	;
  2082                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2083                              <1> 	; KEYBOARD I/O								      :
  2084                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2085                              <1> 	; INPUT									      :
  2086                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2087                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2088                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2089                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2090                              <1> 	;-----------------------------------------------------------------------------:
  2091                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2092                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2093                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2094                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2095                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2096                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2097                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2098                              <1> 	;-----------------------------------------------------------------------------:	
  2099                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2100                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2101                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2102                              <1> 	;-----------------------------------------------------------------------------:	
  2103                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2104                              <1> 	;	      (AL) = 05H                                                      :
  2105                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2106                              <1> 	;		       							      :
  2107                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2108                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2109                              <1> 	;                     --------------------------------------------            :
  2110                              <1> 	;			00H        30.0        10H        7.5                 :
  2111                              <1> 	;			01H        26.7        11H        6.7                 :
  2112                              <1> 	;			02H        24.0        12H        6.0                 :
  2113                              <1> 	;			03H        21.8        13H        5.5                 :
  2114                              <1> 	;			04H        20.0        14H        5.0                 :
  2115                              <1> 	;			05H        18.5        15H        4.6                 :
  2116                              <1> 	;			06H        17.1        16H        4.3                 :
  2117                              <1> 	;			07H        16.0        17H        4.0                 :
  2118                              <1> 	;			08H        15.0        18H        3.7                 :
  2119                              <1> 	;			09H        13.3        19H        3.3                 :
  2120                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2121                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2122                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2123                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2124                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2125                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2126                              <1> 	;									      :
  2127                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2128                              <1> 	;		       							      :
  2129                              <1> 	;                     REGISTER     DELAY                                      :
  2130                              <1> 	;                      VALUE       VALUE                                      :
  2131                              <1> 	;                     ------------------                                      :
  2132                              <1> 	;			00H        250 ms                                     :
  2133                              <1> 	;			01H        500 ms                                     :
  2134                              <1> 	;			02H        750 ms                                     :
  2135                              <1> 	;			03H       1000 ms                                     :
  2136                              <1> 	;-----------------------------------------------------------------------------:
  2137                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2138                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2139                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2140                              <1> 	;		           (CH) = SCAN CODE                                   :
  2141                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2142                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2143                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2144                              <1> 	;-----------------------------------------------------------------------------:		
  2145                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2146                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2147                              <1> 	;-----------------------------------------------------------------------------:
  2148                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2149                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2150                              <1> 	;-----------------------------------------------------------------------------:	
  2151                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2152                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2153                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2154                              <1> 	; OUTPUT					                              :
  2155                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2156                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2157                              <1> 	;------------------------------------------------------------------------------
  2158                              <1> 	
  2159 00000BFB FB                  <1> 	sti				; INTERRUPTS BACK ON
  2160 00000BFC 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2161 00000BFD 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2162                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2163 00000BFE 66BB1000            <1>         mov     bx, KDATA 
  2164 00000C02 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2165 00000C04 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2166 00000C06 742D                <1> 	jz	short _K1		; ASCII_READ
  2167 00000C08 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2168 00000C0A 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2169 00000C0C FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2170 00000C0E 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2171 00000C10 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2172 00000C12 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2173 00000C14 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2174 00000C17 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2175                              <1> _KIO1:	
  2176 00000C19 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2177 00000C1C 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2178 00000C1E FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2179 00000C20 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2180 00000C22 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2181 00000C24 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2182                              <1> _KIO_EXIT:
  2183                              <1> 	;pop	ecx			; RECOVER REGISTER
  2184 00000C26 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2185 00000C27 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2186 00000C28 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2187                              <1> 
  2188                              <1> 	;-----	ASCII CHARACTER
  2189                              <1> _K1E:	
  2190 00000C29 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2191 00000C2E E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2192 00000C33 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2193                              <1> _K1:	
  2194 00000C35 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2195 00000C3A E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2196 00000C3F 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2197                              <1> _K1A:
  2198 00000C41 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2199                              <1> 
  2200                              <1> 	;-----	ASCII STATUS
  2201                              <1> _K2E:	
  2202 00000C43 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2203 00000C48 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2204 00000C4A 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2205 00000C4B E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2206 00000C50 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2207                              <1> _K2:	
  2208 00000C52 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2209 00000C57 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2210 00000C59 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2211 00000C5A E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2212 00000C5F 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2213 00000C61 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2214 00000C62 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2215 00000C67 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2216                              <1> _K2A:
  2217 00000C69 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2218                              <1> _K2B:
  2219                              <1> 	;pop	ecx			; RECOVER REGISTER
  2220 00000C6A 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2221 00000C6B 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2222 00000C6C CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2223                              <1> 
  2224                              <1> ; 24/12/2021
  2225                              <1> ;	;-----	SHIFT STATUS
  2226                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2227                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2228                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2229                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2230                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2231                              <1> ;       shl	ah, 5
  2232                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2233                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2234                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2235                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2236                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2237                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2238                              <1> ;_K3:
  2239                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2240                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2241                              <1> 
  2242                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2243                              <1> _K300:
  2244 00000C6F 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2245 00000C71 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2246 00000C73 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2247 00000C76 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2248 00000C78 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2249 00000C7B 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2250 00000C7D B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2251 00000C7F E87C060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2252                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2253                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2254 00000C84 C0E705              <1> 	shl	bh, 5
  2255 00000C87 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2256 00000C89 08F8                <1> 	or	al, bh			; AND DELAY
  2257 00000C8B E870060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2258 00000C90 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2259                              <1> 
  2260                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2261                              <1> _K500:
  2262 00000C92 56                  <1> 	push	esi			; SAVE SI (esi)
  2263 00000C93 FA                  <1> 	cli				; 
  2264 00000C94 8B1D[145F0000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2265 00000C9A 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2266 00000C9C E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2267 00000CA1 3B1D[105F0000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2268 00000CA7 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2269 00000CA9 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2270 00000CAC 891D[145F0000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2271 00000CB2 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2272 00000CB4 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2273                              <1> _K502:
  2274 00000CB6 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2275                              <1> _K504:
  2276 00000CB8 FB                  <1> 	sti				
  2277 00000CB9 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2278 00000CBA E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2279                              <1> 
  2280                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2281                              <1> _K1S:
  2282 00000CBF FA                  <1> 	cli	; 03/12/2014
  2283 00000CC0 8B1D[105F0000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2284 00000CC6 3B1D[145F0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2285                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2286 00000CCC 750F                <1> 	jne	short _k1x ; 03/12/2014
  2287                              <1> 	;
  2288                              <1> 	; 03/12/2014
  2289                              <1> 	; 28/08/2014
  2290                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2291                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2292                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2293                              <1> _K1T:                                   ; ASCII READ
  2294 00000CCE FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2295 00000CCF 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2296                              <1> _K1U:	
  2297 00000CD0 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2298 00000CD1 8B1D[105F0000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2299 00000CD7 3B1D[145F0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2300                              <1> _k1x:
  2301 00000CDD 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2302 00000CDE 9C                  <1> 	pushf				; SAVE FLAGS
  2303 00000CDF E8D0060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2304 00000CE4 8A1D[055F0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2305 00000CEA 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2306 00000CEC 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2307 00000CEF 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2308 00000CF1 E86A060000          <1> 	call	SND_LED1
  2309 00000CF6 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2310                              <1> _K1V:
  2311 00000CF7 9D                  <1> 	popf				; RESTORE FLAGS
  2312 00000CF8 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2313 00000CF9 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2314                              <1> 	;
  2315 00000CFB 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2316 00000CFE E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2317 00000D03 891D[105F0000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2318 00000D09 C3                  <1> 	retn				; RETURN
  2319                              <1> 
  2320                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2321                              <1> _K2S:
  2322 00000D0A FA                  <1> 	cli				; INTERRUPTS OFF
  2323 00000D0B 8B1D[105F0000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2324 00000D11 3B1D[145F0000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2325 00000D17 668B03              <1> 	mov	ax, [ebx]
  2326 00000D1A 9C                  <1> 	pushf				; SAVE FLAGS
  2327                              <1> 	;push	ax			; SAVE CODE
  2328                              <1> 	; 24/12/2021
  2329 00000D1B 50                  <1> 	push	eax
  2330 00000D1C E893060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2331 00000D21 8A1D[055F0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2332 00000D27 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2333 00000D29 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2334 00000D2C 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2335 00000D2E E816060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2336                              <1> _K2T:
  2337                              <1> 	;pop	ax			; RESTORE CODE
  2338                              <1> 	; 24/12/2021
  2339 00000D33 58                  <1> 	pop	eax
  2340 00000D34 9D                  <1> 	popf				; RESTORE FLAGS
  2341 00000D35 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2342 00000D36 C3                  <1> 	retn				; RETURN
  2343                              <1> 
  2344                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2345                              <1> _KIO_E_XLAT:
  2346 00000D37 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2347 00000D39 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2348 00000D3B 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2349 00000D3D 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2350 00000D3F 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2351                              <1> _KIO_E_RET:				
  2352 00000D41 C3                  <1> 	retn				; GO BACK
  2353                              <1> 
  2354                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2355                              <1> _KIO_S_XLAT:
  2356 00000D42 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2357 00000D45 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2358 00000D47 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2359 00000D49 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2360 00000D4B 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2361 00000D4D 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2362 00000D4F B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2363                              <1> _kio_ret: ; 03/12/2014
  2364 00000D51 F8                  <1> 	clc
  2365 00000D52 C3                  <1> 	retn
  2366                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2367                              <1> _KIO_S1:				
  2368 00000D53 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2369                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2370 00000D55 C3                  <1> 	retn
  2371                              <1> _KIO_S2:		
  2372 00000D56 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2373 00000D59 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2374 00000D5B 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2375 00000D5D 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2376 00000D5F 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2377 00000D61 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2378 00000D63 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2379                              <1> _KIO_S3:
  2380 00000D65 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2381                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2382 00000D67 75E8                <1> 	jne	short _kio_ret
  2383 00000D69 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2384 00000D6B 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2385 00000D6D 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2386                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2387                              <1> _KIO_USE:
  2388                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2389 00000D6F C3                  <1> 	retn				; RETURN	
  2390                              <1> _KIO_DIS:
  2391 00000D70 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2392 00000D71 C3                  <1> 	retn				; RETURN
  2393                              <1> 
  2394                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2395                              <1> _K4:    
  2396 00000D72 43                  <1> 	inc     ebx
  2397 00000D73 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2398 00000D74 3B1D[0C5F0000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2399                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2400 00000D7A 7206                <1> 	jb	short _K5
  2401 00000D7C 8B1D[085F0000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2402                              <1> _K5:
  2403 00000D82 C3                  <1> 	retn
  2404                              <1> 
  2405                              <1> ; 20/02/2015
  2406                              <1> ; 05/12/2014
  2407                              <1> ; 26/08/2014
  2408                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2409                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2410                              <1> ;
  2411                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2412                              <1> ; rombios source code (06/10/1985)
  2413                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2414                              <1> 
  2415                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2416                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2417                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2418                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2419                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2420                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2421                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2422                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2423                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2424                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2425                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2426                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2427                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2428                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2429                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2430                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2431                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2432                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2433                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2434                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2435                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2436                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2437                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2438                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2439                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2440                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2441                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2442                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2443                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2444                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2445                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2446                              <1> F11_M		equ	87		; F11 KEY MAKE
  2447                              <1> F12_M		equ	88		; F12 KEY MAKE
  2448                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2449                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2450                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2451                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2452                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2453                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2454                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2455                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2456                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2457                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2458                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2459                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2460                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2461                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2462                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2463                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2464                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2465                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2466                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2467                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2468                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2469                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2470                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2471                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2472                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2473                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2474                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2475                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2476                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2477                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2478                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2479                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2480                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2481                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2482                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2483                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2484                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2485                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2486                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2487                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2488                              <1> ;
  2489                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2490                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2491                              <1> INTA00		equ	020h		; 8259 PORT
  2492                              <1> 
  2493                              <1> 
  2494                              <1> kb_int:
  2495                              <1> 
  2496                              <1> ; 13/06/2022
  2497                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2498                              <1> ; 17/10/2015 ('ctrlbrk') 
  2499                              <1> ; 05/12/2014
  2500                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2501                              <1> 	;	      instead of pc-at bios - 1985-)
  2502                              <1> ; 26/08/2014
  2503                              <1> ;
  2504                              <1> ; 03/06/86  KEYBOARD BIOS
  2505                              <1> ;
  2506                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2507                              <1> ;										;
  2508                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2509                              <1> ;										;
  2510                              <1> ;--------------------------------------------------------------------------------
  2511                              <1> 
  2512                              <1> KB_INT_1:
  2513 00000D83 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2514                              <1> 	;push	ebp
  2515 00000D84 50                  <1> 	push	eax
  2516 00000D85 53                  <1> 	push	ebx
  2517 00000D86 51                  <1> 	push	ecx
  2518 00000D87 52                  <1> 	push	edx
  2519 00000D88 56                  <1> 	push	esi
  2520 00000D89 57                  <1> 	push	edi
  2521 00000D8A 1E                  <1> 	push	ds
  2522 00000D8B 06                  <1> 	push	es
  2523 00000D8C FC                  <1> 	cld				; FORWARD DIRECTION
  2524 00000D8D 66B81000            <1> 	mov	ax, KDATA
  2525 00000D91 8ED8                <1> 	mov	ds, ax
  2526 00000D93 8EC0                <1> 	mov	es, ax
  2527                              <1> 	;
  2528                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2529 00000D95 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2530 00000D97 E852050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2531 00000D9C FA                  <1> 	cli				; DISABLE INTERRUPTS
  2532 00000D9D B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2533                              <1> KB_INT_01:
  2534 00000DA2 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2535 00000DA4 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2536 00000DA6 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2537                              <1> 	;
  2538                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2539 00000DA8 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2540                              <1> 	;
  2541                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2542                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2543                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2544                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2545                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2546                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2547                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2548                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2549                              <1> 	;
  2550                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2551                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2552 00000DAA FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2553 00000DAB 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2554 00000DAD 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2555                              <1> 	;
  2556                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2557 00000DAF 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2558 00000DB1 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2559                              <1> 	;
  2560                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2561 00000DB3 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2562 00000DB4 800D[055F0000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2563 00000DBB E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2564                              <1> 	;
  2565                              <1> 	;-----	RESEND THE LAST BYTE
  2566                              <1> KB_INT_4:
  2567 00000DC0 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2568 00000DC1 800D[055F0000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2569 00000DC8 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2570                              <1> 	;
  2571                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2572                              <1> KB_INT_2:
  2573                              <1> 	;push 	ax			; SAVE DATA IN
  2574                              <1> 	; 24/12/2021
  2575 00000DCD 50                  <1> 	push	eax
  2576 00000DCE E8E1050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2577 00000DD3 8A1D[055F0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2578 00000DD9 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2579 00000DDB 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2580 00000DDE 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2581 00000DE0 E864050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2582                              <1> UP0:
  2583                              <1> 	;pop	ax			; RESTORE DATA IN
  2584                              <1> 	; 24/12/2021
  2585 00000DE5 58                  <1> 	pop	eax
  2586                              <1> ;------------------------------------------------------------------------
  2587                              <1> ;	START OF KEY PROCESSING						;
  2588                              <1> ;------------------------------------------------------------------------
  2589 00000DE6 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2590                              <1> 	;
  2591                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2592 00000DE8 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2593                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2594                              <1> 	; 24/12/2021
  2595 00000DEA 7505                <1> 	jne	short K16
  2596 00000DEC E9E9040000          <1> 	jmp	K62
  2597                              <1> K16:	
  2598 00000DF1 8A3D[065F0000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2599                              <1> 	;
  2600                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2601 00000DF7 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2602 00000DFA 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2603 00000DFC 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2604 00000DFE 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2605 00000E00 7507                <1> 	jne	short RST_RD_ID
  2606 00000E02 800D[065F0000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2607                              <1> RST_RD_ID:
  2608 00000E09 8025[065F0000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2609 00000E10 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2610                              <1> 	; 24/12/2021
  2611                              <1> 	;jmp	K26
  2612                              <1> 	;
  2613                              <1> TST_ID_2:
  2614 00000E12 8025[065F0000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2615 00000E19 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2616 00000E1B 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2617 00000E1D 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2618 00000E1F 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2619                              <1> 	; 24/12/2021
  2620                              <1> 	;jne	K26
  2621                              <1> 	;
  2622                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2623 00000E21 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2624 00000E24 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2625 00000E26 800D[035F0000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2626 00000E2D E817050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2627                              <1> KX_BIT:
  2628 00000E32 800D[065F0000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2629 00000E39 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2630                              <1> 	;
  2631                              <1> NOT_ID:
  2632 00000E3E 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2633 00000E40 750E                <1> 	jne	short TEST_E1
  2634 00000E42 800D[065F0000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2635 00000E49 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2636                              <1> 	; 24/12/2021
  2637 00000E4B E9DA010000          <1> 	jmp	K26A	
  2638                              <1> TEST_E1:	
  2639 00000E50 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2640 00000E52 750C                <1> 	jne	short NOT_HC
  2641 00000E54 800D[065F0000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2642 00000E5B E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2643                              <1> 	;
  2644                              <1> NOT_HC:
  2645 00000E60 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2646 00000E62 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2647 00000E65 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2648                              <1> 	;
  2649 00000E67 BF[EE5D0000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2650 00000E6C AE                  <1> 	scasb
  2651                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2652                              <1> 	; 24/12/2021
  2653 00000E6D 7458                <1> 	je	short K16B
  2654 00000E6F AE                  <1> 	scasb
  2655 00000E70 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2656 00000E72 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2657                              <1> 	; 24/12/2021
  2658                              <1> 	;jmp	K26
  2659                              <1> 	;
  2660                              <1> NOT_LC_E0:
  2661 00000E74 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2662 00000E77 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2663 00000E79 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2664 00000E7E BF[EC5D0000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2665 00000E83 F2AE                <1> 	repne	scasb			; CHECK IT
  2666 00000E85 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2667                              <1> 	; 24/12/2021
  2668                              <1> 	;je	K26A			
  2669                              <1> 	;
  2670 00000E87 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2671 00000E89 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2672                              <1> 	; 24/12/2021
  2673                              <1> 	;jne	K26
  2674 00000E8B F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2675 00000E8E 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2676                              <1> 	; 24/12/2021
  2677                              <1> 	;jnz	K26
  2678                              <1>         ; 20/02/2015 
  2679 00000E90 F605[045F0000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2680 00000E97 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2681                              <1> 	; 24/12/2021
  2682                              <1> 	;jnz	K26
  2683 00000E99 E9D2020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2684                              <1> 	;
  2685                              <1> 	;-----	TEST FOR SYSTEM KEY
  2686                              <1> T_SYS_KEY:
  2687 00000E9E 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2688 00000EA0 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2689                              <1> 	;
  2690 00000EA2 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2691 00000EA5 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2692                              <1> 	;
  2693 00000EA7 F605[045F0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2694 00000EAE 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2695                              <1> 	;jnz	K26			
  2696                              <1> 	;
  2697 00000EB0 800D[045F0000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2698 00000EB7 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2699 00000EB9 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2700                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2701 00000EBB B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2702 00000EBD E82C040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2703                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2704                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2705                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2706                              <1> 	;INT	15H			; USER INTERRUPT	
  2707 00000EC2 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2708                              <1> 	;
  2709 00000EC7 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2710                              <1> 	;
  2711                              <1> K16C:
  2712 00000ECC 8025[045F0000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2713 00000ED3 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2714 00000ED5 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2715                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2716                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2717                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2718                              <1> 	;
  2719                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2720                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2721                              <1> 	;INT	15H			; USER INTERRUPT
  2722                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2723                              <1> 	;
  2724 00000ED7 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2725                              <1> 	;
  2726                              <1> 	;-----	TEST FOR SHIFT KEYS
  2727                              <1> K16A:
  2728 00000EDC 8A1D[035F0000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2729 00000EE2 BF[E85D0000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2730 00000EE7 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2731 00000EEC F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2732 00000EEE 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2733                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2734                              <1> 	; 24/12/2021
  2735 00000EF0 7405                <1> 	je	short K17
  2736 00000EF2 E914010000          <1> 	jmp	K25
  2737                              <1> 	;
  2738                              <1> 	;------	SHIFT KEY FOUND
  2739                              <1> K17:
  2740 00000EF7 81EF[E95D0000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2741 00000EFD 8AA7[F05D0000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2742 00000F03 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2743 00000F05 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2744                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2745                              <1> 	; 24/12/2021
  2746 00000F07 7405                <1> 	jz	short K17C
  2747 00000F09 E999000000          <1> 	jmp	K23
  2748                              <1> 	;
  2749                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2750                              <1> K17C:
  2751 00000F0E 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2752 00000F11 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2753                              <1> 	;
  2754                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2755 00000F13 0825[035F0000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2756 00000F19 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2757 00000F1B 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2758                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2759                              <1> 	; 24/12/2021
  2760 00000F1D E901010000          <1> 	jmp	K26
  2761                              <1> K17D:
  2762 00000F22 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2763 00000F25 740B                <1> 	jz 	short K17E		; NO, JUMP
  2764 00000F27 0825[065F0000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2765 00000F2D E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2766                              <1> K17E:
  2767 00000F32 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2768 00000F34 0825[045F0000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2769 00000F3A E9E4000000          <1> 	jmp	K26
  2770                              <1> 	;
  2771                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2772                              <1> K18:					; SHIFT-TOGGLE
  2773 00000F3F F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2774 00000F42 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2775                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2776                              <1> 	; 24/12/2021
  2777 00000F44 E9C2000000          <1> 	jmp	K25
  2778                              <1> K18A:
  2779 00000F49 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2780 00000F4B 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2781 00000F4D F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2782 00000F50 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2783                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2784                              <1> 	; 24/12/2021
  2785 00000F52 E9B4000000          <1> 	jmp	K25
  2786                              <1> K18B:
  2787 00000F57 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2788 00000F5A 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2789                              <1> K19:	
  2790 00000F5C F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2791 00000F5F 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2792 00000F61 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2793 00000F64 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2794                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2795 00000F66 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2796 00000F68 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2797                              <1> K21:					; MIGHT BE NUMERIC
  2798 00000F6D F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2799 00000F70 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2800                              <1> 	;
  2801                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2802 00000F72 8425[045F0000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2803                              <1> 	;jnz	K26
  2804                              <1> 	; 24/12/2021
  2805 00000F78 7405                <1> 	jz	short K22A
  2806 00000F7A E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2807                              <1> K22A:
  2808 00000F7F 0825[045F0000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2809 00000F85 3025[035F0000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2810                              <1> 	;
  2811                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2812 00000F8B F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2813 00000F8E 7407                <1> 	jz	short K22B		; GO IF NOT
  2814                              <1> 	;
  2815                              <1> 	; 24/12/2021
  2816                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2817 00000F90 50                  <1> 	push	eax
  2818 00000F91 E8B3030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2819                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2820 00000F96 58                  <1> 	pop	eax
  2821                              <1> K22B:
  2822 00000F97 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2823                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2824                              <1> 	; 24/12/2021
  2825 00000F99 7405                <1> 	je	short K22C
  2826 00000F9B E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2827                              <1> K22C:
  2828 00000FA0 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2829 00000FA2 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2830                              <1> 	;
  2831                              <1> 	;-----	BREAK SHIFT FOUND
  2832                              <1> K23:					; BREAK-SHIFT-FOUND
  2833 00000FA7 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2834 00000FAA F6D4                <1> 	not	ah			; INVERT MASK
  2835 00000FAC 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2836 00000FAE 2025[035F0000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2837 00000FB4 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2838 00000FB7 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2839                              <1> 	;
  2840 00000FB9 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2841 00000FBC 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2842 00000FBE 2025[065F0000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2843 00000FC4 EB08                <1> 	jmp	short K23B		; CONTINUE
  2844                              <1> K23A:
  2845 00000FC6 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2846 00000FC8 2025[045F0000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2847                              <1> K23B:
  2848 00000FCE 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2849 00000FD0 A0[065F0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2850 00000FD5 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2851 00000FD7 0A05[045F0000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2852 00000FDD D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2853 00000FDF 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2854 00000FE1 0805[035F0000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2855 00000FE7 88E0                <1> 	mov	al, ah
  2856                              <1> K23D:
  2857 00000FE9 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2858 00000FEB 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2859                              <1> 	;	
  2860                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2861 00000FED A0[075F0000]        <1> 	mov	al, [ALT_INPUT]
  2862 00000FF2 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2863 00000FF4 8825[075F0000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2864 00000FFA 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2865 00000FFC 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2866 00000FFE E9B4020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2867                              <1> 	;
  2868                              <1> K24:					; BREAK-TOGGLE
  2869 00001003 2025[045F0000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2870 00001009 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2871                              <1> 	;
  2872                              <1> 	;-----	TEST FOR HOLD STATE
  2873                              <1> 					; AL, AH = SCAN CODE
  2874                              <1> K25:					; NO-SHIFT-FOUND
  2875 0000100B 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2876 0000100D 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2877 0000100F F605[045F0000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2878 00001016 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2879 00001018 3C45                <1> 	cmp	al, NUM_KEY
  2880 0000101A 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2881 0000101C 8025[045F0000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2882                              <1> 	;
  2883                              <1> K26:
  2884 00001023 8025[065F0000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2885                              <1> K26A:					; INTERRUPT-RETURN
  2886 0000102A FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2887 0000102B B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2888 0000102D E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2889                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2890 0000102F B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2891 00001031 E8B8020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2892                              <1> K27A:
  2893 00001036 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2894 00001037 07                  <1> 	pop	es			; RESTORE REGISTERS
  2895 00001038 1F                  <1> 	pop	ds
  2896 00001039 5F                  <1> 	pop	edi
  2897 0000103A 5E                  <1> 	pop	esi
  2898 0000103B 5A                  <1> 	pop	edx
  2899 0000103C 59                  <1> 	pop	ecx
  2900 0000103D 5B                  <1> 	pop	ebx
  2901 0000103E 58                  <1> 	pop	eax
  2902                              <1> 	;pop	ebp
  2903 0000103F CF                  <1> 	iret				; RETURN
  2904                              <1> 
  2905                              <1> 	;-----	NOT IN	HOLD STATE
  2906                              <1> K28:					; NO-HOLD-STATE
  2907 00001040 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2908 00001042 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2909                              <1> 	;
  2910 00001044 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2911 00001047 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2912                              <1>         ; 24/12/2021
  2913                              <1> 	;jz      K38
  2914                              <1> 	;
  2915 00001049 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2916 0000104C 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2917                              <1> 	; 28/02/2015
  2918 0000104E F605[045F0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2919 00001055 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2920                              <1> 	; 24/12/2021
  2921                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2922                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2923 00001057 E9CD000000          <1> K28A:	jmp	K38
  2924                              <1> 	;
  2925                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2926                              <1> K29:					; TEST-RESET
  2927 0000105C F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2928 0000105F 740B                <1> 	jz	short K31		; NO_RESET
  2929 00001061 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2930 00001063 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2931                              <1> 	;
  2932                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2933                              <1>  	; 26/08/2014
  2934                              <1> cpu_reset:
  2935                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2936                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2937 00001065 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2938 00001067 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2939                              <1> khere:
  2940 00001069 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2941 0000106A EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2942                              <1> 
  2943                              <1> 	;
  2944                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2945                              <1> K31:					; NO-RESET
  2946 0000106C 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2947 0000106E 7507                <1> 	jne	short K311		; NOT THERE
  2948 00001070 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2949 00001072 E932020000          <1>         jmp     K57                     ; BUFFER_FILL
  2950                              <1> K311:
  2951 00001077 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2952 00001079 7509                <1> 	jne	short K312		; NOT THERE
  2953 0000107B 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2954 0000107F E925020000          <1>         jmp     K57                     ; BUFFER_FILL
  2955                              <1> K312:
  2956 00001084 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2957 00001086 7471                <1>         je	short K37B              ; GO PROCESS
  2958 00001088 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2959 0000108A 746D                <1>         je	short K37B              ; GO PROCESS
  2960                              <1> 	;
  2961                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2962                              <1> K32:					; ALT-KEY-PAD
  2963 0000108C BF[C45D0000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2964 00001091 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2965 00001096 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2966 00001098 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2967 0000109A F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2968                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2969                              <1> 	; 24/12/2021
  2970 0000109D 751C                <1> 	jnz	short K32B
  2971 0000109F 81EF[C55D0000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2972 000010A5 A0[075F0000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2973 000010AA B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2974 000010AC F6E4                <1> 	mul	ah
  2975 000010AE 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2976 000010B1 A2[075F0000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2977                              <1> K32A:
  2978 000010B6 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2979                              <1> K32B:
  2980                              <1> 	; 24/12/2021
  2981 000010BB EB66                <1> 	jmp	K37C
  2982                              <1> 	;
  2983                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2984                              <1> K33:					; NO-ALT-KEYPAD
  2985 000010BD C605[075F0000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2986 000010C4 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2987 000010C9 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2988 000010CB 744F                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2989                              <1> 	;
  2990                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2991                              <1> K34:					; ALT-TOP-ROW
  2992 000010CD 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2993 000010CF 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2994 000010D1 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2995 000010D3 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2996 000010D5 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2997 000010D8 EB42                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2998                              <1> 	;
  2999                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  3000                              <1> K35:					; ALT-FUNCTION
  3001 000010DA 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  3002 000010DC 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  3003 000010DE 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  3004 000010E0 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  3005 000010E2 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  3006 000010E5 EB35                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  3007                              <1> K35A:
  3008 000010E7 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  3009 000010EA 7425                <1> 	jz	short K37		; NO, JUMP
  3010 000010EC 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  3011 000010EE 7510                <1>         jne     short K35B              ; NOT THERE
  3012 000010F0 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  3013 000010F4 E9B0010000          <1> 	jmp	K57			; BUFFER FILL
  3014                              <1> K37B:
  3015 000010F9 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  3016 000010FB E9A9010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  3017                              <1> K35B:
  3018 00001100 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3019 00001102 741F                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3020 00001104 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3021 00001106 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3022                              <1>         ; 24/12/2021
  3023                              <1> 	;jne	K26
  3024 00001108 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3025 0000110C E998010000          <1> 	jmp	K57			; BUFFER FILL
  3026                              <1> K37:
  3027 00001111 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3028 00001113 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3029 00001115 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3030 00001117 779D                <1>         ja	short K32A		; IF SO, IGNORE
  3031                              <1> 	; 13/06/2022
  3032                              <1>         ;ja	K26
  3033 00001119 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3034                              <1> K37A:
  3035 0000111C B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3036 0000111E E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3037                              <1> K37C:
  3038 00001123 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3039 00001125 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3040 00001127 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3041                              <1> 	;
  3042                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3043                              <1> K38:					; NOT-ALT-SHIFT
  3044                              <1> 					; BL STILL HAS SHIFT FLAGS
  3045 00001129 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3046 0000112C 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3047                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3048                              <1> 	; 24/12/2021
  3049 0000112E E9AB000000          <1> 	jmp	K44
  3050                              <1> 	;
  3051                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3052                              <1> 	;-----	TEST FOR BREAK
  3053                              <1> K38A:
  3054 00001133 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3055 00001135 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3056 00001137 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3057 0000113A 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3058 0000113C F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3059 0000113F 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3060                              <1> K38B:
  3061 00001141 8B1D[105F0000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3062 00001147 891D[145F0000]      <1> 	mov	[BUFFER_TAIL], ebx
  3063 0000114D C605[025F0000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3064                              <1> 	;
  3065                              <1> 	;-----	ENABLE KEYBOARD
  3066 00001154 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3067 00001156 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3068                              <1> 	;
  3069                              <1> 	; CTRL+BREAK code here !!!
  3070                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3071                              <1> 	; 17/10/2015	
  3072 0000115B E8AB1A0000          <1> 	call	ctrlbrk ; control+break subroutine
  3073                              <1> 	;
  3074                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3075                              <1> 	; 24/12/2021
  3076 00001160 29C0                <1> 	sub	eax, eax
  3077 00001162 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3078                              <1> 	;
  3079                              <1> 	;-----	TEST FOR PAUSE
  3080                              <1> K39:					; NO_BREAK
  3081 00001167 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3082 0000116A 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3083 0000116C 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3084 0000116E 7533                <1> 	jne	short K41		; NO-PAUSE
  3085                              <1> K39P:
  3086 00001170 800D[045F0000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3087                              <1> 	;
  3088                              <1> 	;-----	ENABLE KEYBOARD
  3089 00001177 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3090 00001179 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3091                              <1> K39A:
  3092 0000117E B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3093 00001180 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3094                              <1> 	;
  3095                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3096 00001182 803D[005F0000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3097 00001189 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3098 0000118B 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3099 0000118F A0[015F0000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3100 00001194 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3101                              <1> 	;
  3102                              <1> K40:					; PAUSE-LOOP
  3103 00001195 F605[045F0000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3104 0000119C 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3105                              <1> 	;
  3106 0000119E E98CFEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3107                              <1>         ;
  3108                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3109                              <1> K41:					; NO-PAUSE
  3110 000011A3 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3111 000011A5 7513                <1> 	jne	short K42		; NOT-KEY-55
  3112 000011A7 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3113 000011AA 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3114 000011AC F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3115 000011AF 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3116                              <1> K41A:	
  3117 000011B1 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3118 000011B5 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3119                              <1> 	;
  3120                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3121                              <1> K42:					; NOT-KEY-55
  3122 000011BA 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3123 000011BC 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3124 000011BE 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3125 000011C0 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3126 000011C2 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3127 000011C5 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3128 000011C7 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3129 000011CB E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3130                              <1> K42A:
  3131                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3132 000011D0 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3133                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3134                              <1> 	;;jb	K56 ; 20/02/2015
  3135                              <1> 	;;jmp	K64 ; 20/02/2015
  3136                              <1> K42B:
  3137 000011D2 BB[F85D0000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3138                              <1> 	;;jmp	K64
  3139                              <1> 	;jb	K56 ;; 20/02/2015	
  3140                              <1> 	; 24/12/2021
  3141 000011D7 7267                <1> 	jb	short K45F
  3142 000011D9 E9B9000000          <1> 	jmp	K64	
  3143                              <1>         ;
  3144                              <1> 	;-----	NOT IN CONTROL SHIFT
  3145                              <1> K44:					; NOT-CTL-SHIFT
  3146 000011DE 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3147 000011E0 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3148 000011E2 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3149 000011E5 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3150 000011E7 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3151 000011EA 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3152 000011EC EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3153                              <1> K44A:
  3154 000011EE F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3155 000011F1 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3156                              <1> 	;
  3157                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3158                              <1> K44B:
  3159 000011F3 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3160 000011F5 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3161 000011FA B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3162 000011FC E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3163                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3164                              <1> 	;PUSH 	BP			; SAVE POINTER
  3165                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3166                              <1> 	;POP	BP			; RESTORE POINTER
  3167 000011FE 8025[065F0000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3168 00001205 E925FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3169                              <1> 	;
  3170                              <1> 	;-----	HANDLE IN-CORE KEYS
  3171                              <1> K45:					; NOT-PRINT-SCREEN
  3172 0000120A 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3173 0000120C 7734                <1> 	ja	short K46		; JUMP IF NOT
  3174 0000120E 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3175 00001210 7505                <1> 	jne	short K45A		; NO, JUMP
  3176 00001212 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3177 00001215 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3178                              <1> K45A:
  3179 00001217 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3180 0000121C BF[CE5D0000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3181 00001221 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3182                              <1> 		; 20/02/2015
  3183 00001223 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3184                              <1> 	;
  3185 00001225 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3186 00001228 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3187                              <1> K45B:
  3188 0000122A F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3189 0000122D 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3190                              <1> 					; NO, LOWERCASE
  3191                              <1> K45C:
  3192 0000122F BB[505E0000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3193 00001234 EB51                <1> 	jmp	short K56	
  3194                              <1> K45D:					; ALMOST-CAPS-STATE
  3195 00001236 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3196 00001239 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3197                              <1> K45E:
  3198 0000123B BB[A85E0000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3199 00001240 EB45                <1> K45F:	jmp	short K56
  3200                              <1> 	;
  3201                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3202                              <1> K46:					; NOT IN-CORE AREA
  3203 00001242 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3204                              <1> 	;ja	short K47		; JUMP IF NOT
  3205                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3206 00001244 7635                <1> 	jna	short K53		
  3207                              <1> 	;
  3208                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3209                              <1> K47:					; NOT F1 - F10
  3210 00001246 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3211 00001248 772D                <1> 	ja	short K52		; JUMP IF NOT
  3212                              <1> 	;
  3213                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3214                              <1> K48:
  3215 0000124A 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3216 0000124C 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3217 0000124E 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3218 00001250 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3219 00001252 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3220 00001255 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3221                              <1> 	;		
  3222 00001257 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3223 0000125A 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3224 0000125C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3225                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3226 0000125F 75DA                <1> 	jnz	short K45E
  3227                              <1> 	;
  3228                              <1> 	;-----	BASE CASE FOR KEYPAD
  3229                              <1> K49:					
  3230 00001261 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3231 00001263 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3232 00001265 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3233 00001267 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3234                              <1> K49A:
  3235 00001269 BB[505E0000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3236 0000126E EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3237                              <1> 	;
  3238                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3239                              <1> K50:					; ALMOST-NUM-STATE
  3240 00001270 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3241 00001273 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3242 00001275 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3243                              <1> 	;
  3244                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3245                              <1> K52:					; NOT A NUMPAD KEY
  3246 00001277 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3247                              <1> 	;jne	short K53		; JUMP IF NOT
  3248                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3249 00001279 74AF                <1> 	je	short K45B		
  3250                              <1> 	;
  3251                              <1> 	;-----	MUST BE F11 OR F12 
  3252                              <1> K53:					; F1 - F10 COME HERE, TOO
  3253 0000127B F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3254 0000127E 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3255                              <1> 		; 20/02/2015 
  3256 00001280 BB[A85E0000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3257 00001285 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3258                              <1> 	;
  3259                              <1> 	;-----	TRANSLATE THE CHARACTER
  3260                              <1> K56:					; TRANSLATE-CHAR
  3261 00001287 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3262 00001289 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3263 0000128A F605[065F0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3264 00001291 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3265 00001293 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3266 00001295 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3267                              <1> 	;
  3268                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3269                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3270 00001297 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3271 00001299 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3272 0000129A 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3273 0000129C B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3274 0000129E F605[065F0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3275 000012A5 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3276 000012A7 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3277                              <1> 	;
  3278                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3279                              <1> K57:					; BUFFER_FILL
  3280 000012A9 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3281 000012AB 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3282                              <1> 	; 24/12/2021
  3283                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3284 000012AD 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3285                              <1> 	; 24/12/2021
  3286 000012B0 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3287                              <1> 	;je	K26			; INTERRUPT_RETURN
  3288                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3289 000012B2 E96CFDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3290                              <1> K61:					; NOT-CAPS-STATE
  3291 000012B7 8B1D[145F0000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3292 000012BD 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3293 000012BF E8AEFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3294 000012C4 3B1D[105F0000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3295 000012CA 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3296 000012CC 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3297 000012CF 891D[145F0000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3298 000012D5 E949FDFFFF          <1> 	jmp	K26
  3299                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3300                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3301                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3302                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3303                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3304                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3305                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3306                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3307                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3308                              <1> 	;;jmp   K27                    
  3309                              <1> 	;
  3310                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3311                              <1> K62:
  3312 000012DA B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3313 000012DC E620                <1> 	out	INTA00, al
  3314 000012DE 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3315 000012E2 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3316 000012E4 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3317 000012E9 E941FDFFFF          <1> 	jmp     K27			; EXIT   
  3318                              <1> 
  3319                              <1> SHIP_IT:
  3320                              <1> 	;---------------------------------------------------------------------------------
  3321                              <1> 	; SHIP_IT
  3322                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3323                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3324                              <1> 	;---------------------------------------------------------------------------------
  3325                              <1> 	;
  3326                              <1> 	;push	ax			; SAVE DATA TO SEND
  3327                              <1> 	; 24/12/2021
  3328 000012EE 50                  <1> 	push	eax
  3329                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3330 000012EF FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3331                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3332 000012F0 B900000100          <1> 	mov	ecx, 10000h			
  3333                              <1> S10:
  3334 000012F5 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3335 000012F7 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3336 000012F9 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3337                              <1> 
  3338                              <1> 	;pop	ax			; GET DATA TO SEND
  3339                              <1> 	; 24/12/2021
  3340 000012FB 58                  <1> 	pop	eax
  3341 000012FC E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3342 000012FE FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3343 000012FF C3                  <1> 	retn				; RETURN TO CALLER
  3344                              <1> 
  3345                              <1> SND_DATA:
  3346                              <1> 	; ---------------------------------------------------------------------------------
  3347                              <1> 	; SND_DATA
  3348                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3349                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3350                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3351                              <1> 	; ---------------------------------------------------------------------------------
  3352                              <1> 	;
  3353                              <1> 	;push	ax			; SAVE REGISTERS
  3354                              <1> 	;push	bx
  3355                              <1> 	; 24/12/2021
  3356 00001300 50                  <1> 	push	eax
  3357 00001301 53                  <1> 	push	ebx
  3358 00001302 51                  <1> 	push	ecx
  3359 00001303 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3360 00001305 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3361                              <1> SD0:
  3362 00001307 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3363 00001308 8025[055F0000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3364                              <1> 	;
  3365                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3366 0000130F B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3367                              <1> SD5:
  3368 00001314 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3369 00001316 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3370 00001318 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3371                              <1> 	;
  3372 0000131A 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3373 0000131C E660                <1> 	out	PORT_A, al		; SEND BYTE
  3374 0000131E FB                  <1> 	sti				; ENABLE INTERRUPTS
  3375                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3376 0000131F B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3377                              <1> SD1:
  3378 00001324 F605[055F0000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3379 0000132B 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3380 0000132D E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3381                              <1> SD2:
  3382 0000132F FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3383 00001331 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3384 00001333 800D[055F0000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3385 0000133A EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3386                              <1> SD3:
  3387 0000133C F605[055F0000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3388 00001343 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3389                              <1> SD4:	
  3390 00001345 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3391                              <1> 	;pop	bx
  3392                              <1> 	;pop	ax
  3393                              <1> 	; 24/12/2021
  3394 00001346 5B                  <1> 	pop	ebx
  3395 00001347 58                  <1> 	pop	eax
  3396 00001348 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3397                              <1> 
  3398                              <1> SND_LED:
  3399                              <1> 	; ---------------------------------------------------------------------------------
  3400                              <1> 	; SND_LED
  3401                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3402                              <1> 	;
  3403                              <1> 	;----------------------------------------------------------------------------------
  3404                              <1> 	;
  3405 00001349 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3406 0000134A F605[055F0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3407 00001351 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3408                              <1> 	;
  3409 00001353 800D[055F0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3410 0000135A B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3411 0000135C E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3412 0000135E EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3413                              <1> SND_LED1:
  3414 00001360 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3415 00001361 F605[055F0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3416 00001368 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3417                              <1> 	;
  3418 0000136A 800D[055F0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3419                              <1> SL0:
  3420 00001371 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3421 00001373 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3422 00001378 FA                  <1> 	cli
  3423 00001379 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3424 0000137E 8025[055F0000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3425 00001385 0805[055F0000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3426 0000138B F605[055F0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3427 00001392 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3428                              <1> 	;
  3429 00001394 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3430 00001399 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3431 0000139A F605[055F0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3432 000013A1 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3433                              <1> SL2:
  3434 000013A3 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3435 000013A5 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3436 000013AA FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3437                              <1> SL3:
  3438 000013AB 8025[055F0000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3439                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3440 000013B2 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3441 000013B3 C3                  <1> 	retn				; RETURN TO CALLER
  3442                              <1> 
  3443                              <1> MAKE_LED:
  3444                              <1> 	;---------------------------------------------------------------------------------
  3445                              <1> 	; MAKE_LED
  3446                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3447                              <1> 	;	THE MODE INDICATORS.
  3448                              <1> 	;---------------------------------------------------------------------------------
  3449                              <1> 	;
  3450                              <1> 	;push 	cx			; SAVE CX
  3451 000013B4 A0[035F0000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3452 000013B9 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3453                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3454                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3455 000013BB C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3456 000013BE 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3457                              <1> 	;pop	cx
  3458 000013C0 C3                  <1> 	retn				; RETURN TO CALLER
  3459                              <1> 
  3460                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3461                              <1> 
  3462                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1883                                  
  1884                                  %include 'video.inc' ; 07/03/2015
  1885                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - VIDEO.INC
  1886                              <1> ; Last Modification: 14/06/2022
  1887                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1888                              <1> ;
  1889                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1890                              <1> 
  1891                              <1> ; 14/06/2022
  1892                              <1> ; 26/02/2022
  1893                              <1> ; 07/02/2022
  1894                              <1> ; 02/02/2022 (simplified scroll up)
  1895                              <1> ; 16/01/2016
  1896                              <1> ; 30/06/2015
  1897                              <1> ; 27/06/2015
  1898                              <1> ; 11/03/2015
  1899                              <1> ; 02/09/2014
  1900                              <1> ; 30/08/2014
  1901                              <1> ; VIDEO FUNCTIONS
  1902                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1903                              <1> 
  1904                              <1> write_tty:
  1905                              <1> 	; 02/02/2022
  1906                              <1> 	; 13/08/2015
  1907                              <1> 	; 02/09/2014
  1908                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1909                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1910                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1911                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1912                              <1> 	;
  1913                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1914                              <1> 	;	   AL = Character to be written
  1915                              <1> 	;	   EBX = Video Page (0 to 7)
  1916                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1917                              <1> 
  1918                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1919                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1920                              <1> 
  1921                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1922                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1923                              <1> ;
  1924                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1925                              <1> ;
  1926                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1927                              <1> ;										:
  1928                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1929                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1930                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1931                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1932                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1933                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1934                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1935                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1936                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1937                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1938                              <1> ;   THE 0 COLOR IS USED.							:
  1939                              <1> ;   ENTRY --									:
  1940                              <1> ;     (AH) = CURRENT CRT MODE							:
  1941                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1942                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1943                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1944                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1945                              <1> ;   EXIT -- 									:
  1946                              <1> ;     ALL REGISTERS SAVED							:
  1947                              <1> ;--------------------------------------------------------------------------------
  1948                              <1> 
  1949 000013C1 FA                  <1> 	cli
  1950                              <1> 	;
  1951                              <1> 	; READ CURSOR (04/12/2013)
  1952                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1953 000013C2 08FF                <1> 	or	bh, bh
  1954                              <1> 	;jnz	beeper
  1955                              <1> 	; 02/02/2022
  1956 000013C4 7405                <1> 	jz	short u14
  1957 000013C6 E992000000          <1> 	jmp	beeper
  1958                              <1> u14:
  1959                              <1> 	; 02/02/2022
  1960                              <1> 	;; 01/09/2014
  1961                              <1> 	;cmp	byte [CRT_MODE], 3
  1962                              <1> 	;je	short m3
  1963                              <1> 	;;
  1964                              <1> 	;call	set_mode
  1965                              <1> m3:
  1966 000013CB 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1967                              <1> 	;shl	si, 1
  1968                              <1> 	; 02/02/2022
  1969 000013CD D1E6                <1> 	shl	esi, 1
  1970 000013CF 81C6[F6640000]      <1> 	add	esi, cursor_posn
  1971 000013D5 668B16              <1> 	mov	dx, [esi]
  1972                              <1> 	;
  1973                              <1> 	; dx now has the current cursor position
  1974                              <1> 	;
  1975 000013D8 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1976 000013DA 7647                <1> 	jbe	short u8
  1977                              <1> 	;
  1978                              <1> 	; write the char to the screen
  1979                              <1> u0:	
  1980                              <1> 	; ah = attribute/color
  1981                              <1> 	; al = character
  1982                              <1> 	; bl = video page number (0 to 7)
  1983                              <1> 	; bh = 0
  1984                              <1> 	;
  1985 000013DC E8D2010000          <1> 	call	write_c_current
  1986                              <1> 	;
  1987                              <1> 	; position the cursor for next char
  1988 000013E1 FEC2                <1> 	inc	dl		; next column
  1989                              <1> 	;cmp	dl, [CRT_COLS]
  1990 000013E3 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1991                              <1>         ;jne	set_cpos
  1992                              <1> 	; 02/02/2022
  1993 000013E6 7405                <1> 	je	short u13
  1994 000013E8 E9DE000000          <1> 	jmp	set_cpos
  1995                              <1> u13:
  1996 000013ED B200                <1> 	mov	dl, 0		; column = 0
  1997                              <1> u10:				; (line feed found)
  1998 000013EF 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1999 000013F2 7228                <1> 	jb 	short u6
  2000                              <1> 	;
  2001                              <1> 	; scroll required
  2002                              <1> u1:	
  2003                              <1> 	; SET CURSOR POSITION (04/12/2013)
  2004 000013F4 E8D2000000          <1> 	call	set_cpos
  2005                              <1> 	;
  2006                              <1> 	; determine value to fill with during scroll
  2007                              <1> u2:
  2008                              <1> 	; READ_AC_CURRENT		:
  2009                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  2010                              <1> 	;    AT THE CURRENT CURSOR POSITION
  2011                              <1> 	;
  2012                              <1> 	; INPUT				
  2013                              <1> 	;	(AH) = CURRENT CRT MODE
  2014                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  2015                              <1> 	;	(DS) = DATA SEGMENT
  2016                              <1> 	;	(ES) = REGEN SEGMENT
  2017                              <1> 	; OUTPUT			
  2018                              <1> 	;	(AL) = CHARACTER READ
  2019                              <1> 	;	(AH) = ATTRIBUTE READ
  2020                              <1> 	;
  2021                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  2022                              <1> 	;
  2023                              <1> 	; bl = video page number
  2024                              <1> 	;
  2025 000013F9 E829010000          <1> 	call	find_position	; get regen location and port address
  2026                              <1> 	; dx = status port
  2027                              <1> 	; esi = cursor location/address
  2028                              <1> p11:
  2029 000013FE FB                  <1> 	sti			; enable interrupts
  2030 000013FF 90                  <1> 	nop			; allow for small interupts window
  2031 00001400 FA                  <1> 	cli			; blocks interrupts for single loop
  2032 00001401 EC                  <1> 	in	al, dx		; get status from adapter
  2033 00001402 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2034 00001404 75F8                <1> 	jnz	short p11	; wait until it is
  2035                              <1> p12:				; now wait for either retrace high
  2036 00001406 EC                  <1> 	in	al, dx		; get status
  2037 00001407 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2038 00001409 74FB                <1> 	jz	short p12	; wait until either is active	
  2039                              <1> p13:
  2040 0000140B 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2041 00001411 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2042                              <1> 	;
  2043                              <1> 	; al = character, ah = attribute
  2044                              <1> 	;
  2045 00001414 FB                  <1> 	sti
  2046                              <1> 	; bl = video page number 	
  2047                              <1> u3:
  2048                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2049                              <1> 	;;sub	cx, cx		; upper left corner
  2050                              <1> 	;;mov	dh, 25-1 	; lower right row
  2051                              <1> 	;;;mov	dl, [CRT_COLS]
  2052                              <1> 	;mov	dl, 80		; lower right column	
  2053                              <1> 	;;dec	dl
  2054                              <1> 	;;mov	dl, 79
  2055                              <1> 
  2056                              <1> 	;;call	scroll_up	; 04/12/2013
  2057                              <1> 	;;; 11/03/2015
  2058                              <1> 	; 02/09/2014
  2059                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2060                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2061                              <1> 	; 11/03/2015
  2062                              <1> 	;sub	cx, cx
  2063                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2064                              <1> 	;
  2065                              <1> 	; 02/02/2022 (simplied scroll up)
  2066                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2067                              <1> 	;
  2068 00001415 B001                <1> 	mov	al, 1		; scroll 1 line up
  2069                              <1> 		; ah = attribute
  2070 00001417 E935010000          <1> 	jmp	scroll_up
  2071                              <1> ;u4:
  2072                              <1> 	;;int	10h		; video-call return
  2073                              <1> 				; scroll up the screen
  2074                              <1> 				; tty return
  2075                              <1> ;u5:
  2076                              <1> 	;retn			; return to the caller
  2077                              <1> 
  2078                              <1> u6:				; set-cursor-inc
  2079 0000141C FEC6                <1> 	inc	dh		; next row
  2080                              <1> 				; set cursor
  2081                              <1> ;u7:					
  2082                              <1> 	;;mov	ah, 02h
  2083                              <1> 	;;jmp	short u4 	; establish the new cursor
  2084                              <1> 	;call	set_cpos
  2085                              <1> 	;jmp 	short u5
  2086 0000141E E9A8000000          <1> 	jmp     set_cpos
  2087                              <1> 
  2088                              <1> 	; check for control characters
  2089                              <1> u8:
  2090 00001423 7434                <1> 	je	short u9
  2091 00001425 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2092 00001427 74C6                <1> 	je	short u10
  2093 00001429 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2094 0000142B 7430                <1> 	je	short u11
  2095 0000142D 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2096                              <1> 	;jne	short u0
  2097 0000142F 7420                <1> 	je	short bs	; 12/12/2013
  2098                              <1> 	; 12/12/2013 (tab stop)
  2099 00001431 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2100 00001433 75A7                <1> 	jne	short u0
  2101 00001435 88D0                <1> 	mov	al, dl
  2102 00001437 6698                <1> 	cbw
  2103 00001439 B108                <1> 	mov	cl, 8
  2104 0000143B F6F1                <1> 	div	cl
  2105 0000143D 28E1                <1> 	sub	cl, ah
  2106                              <1> ts:
  2107                              <1> 	; 02/09/2014
  2108                              <1> 	; 01/09/2014
  2109 0000143F B020                <1> 	mov	al, 20h
  2110                              <1> tsloop:
  2111                              <1> 	;push	cx
  2112                              <1> 	;push	ax
  2113                              <1> 	; 02/02/2022
  2114 00001441 51                  <1> 	push	ecx
  2115 00001442 50                  <1> 	push	eax
  2116 00001443 30FF                <1> 	xor 	bh, bh
  2117                              <1> 	;mov	bl, [active_page]
  2118 00001445 E881FFFFFF          <1> 	call	m3
  2119                              <1> 	; 02/02/2022
  2120 0000144A 58                  <1> 	pop	eax
  2121 0000144B 59                  <1>  	pop	ecx
  2122                              <1> 	;pop	ax  ; ah = attribute/color
  2123                              <1> 	;pop	cx
  2124 0000144C FEC9                <1> 	dec	cl
  2125 0000144E 75F1                <1> 	jnz	short tsloop
  2126 00001450 C3                  <1> 	retn
  2127                              <1> bs:	
  2128                              <1> 	; back space found
  2129 00001451 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2130                              <1> 	;je	short u7 	; set_cursor
  2131 00001453 7476                <1> 	jz	short set_cpos
  2132                              <1> 	;dec	dx     		; no -- just move it back
  2133                              <1> 	; 02/02/2022
  2134 00001455 FECA                <1> 	dec	dl
  2135                              <1> 	;jmp	short u7
  2136 00001457 EB72                <1> 	jmp	short set_cpos
  2137                              <1> 
  2138                              <1> 	; carriage return found
  2139                              <1> u9:
  2140 00001459 B200                <1> 	mov	dl, 0 		; move to first column
  2141                              <1> 	;jmp	short u7
  2142 0000145B EB6E                <1> 	jmp	short set_cpos
  2143                              <1> 
  2144                              <1> 	; line feed found
  2145                              <1> ;u10:
  2146                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2147                              <1> ;	jne	short u6 	; no, just set the cursor
  2148                              <1> ;       jmp     u1              ; yes, scroll the screen
  2149                              <1> 
  2150                              <1> beeper: 
  2151                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2152                              <1> 	; 18/01/2014
  2153                              <1> 	; 03/12/2013
  2154                              <1> 	; bell found
  2155                              <1> u11:
  2156 0000145D FB                  <1> 	sti
  2157 0000145E 3A1D[06650000]      <1> 	cmp	bl, [active_page]
  2158 00001464 7551                <1> 	jne	short u12	; Do not sound the beep 
  2159                              <1> 				; if it is not written on the active page
  2160 00001466 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2161 0000146A B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2162                              <1> 	;call	beep		; sound the pod bell
  2163                              <1> 	;jmp	short u5 	; tty_return
  2164                              <1> 	;retn
  2165                              <1> 	
  2166                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2167                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2168                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2169                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2170                              <1> 
  2171                              <1> beep:
  2172                              <1> 	; 07/02/2015
  2173                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2174                              <1> 	; 18/01/2014
  2175                              <1> 	; 03/12/2013
  2176                              <1> 	;
  2177                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2178                              <1> 	;
  2179                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2180                              <1> 	;
  2181                              <1> 	; ENTRY:
  2182                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2183                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2184                              <1> 	; EXIT:			:
  2185                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2186                              <1> 
  2187 0000146C 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2188 0000146D FA                  <1> 	cli			; block interrupts during update
  2189 0000146E B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2190 00001470 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2191 00001472 EB00                <1> 	jmp	$+2		; I/O delay
  2192 00001474 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2193 00001476 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2194 00001478 EB00                <1> 	jmp	$+2		; I/O delay
  2195 0000147A 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2196 0000147C E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2197 0000147E E461                <1> 	in	al, PORT_B	; get current setting of port
  2198 00001480 88C4                <1> 	mov	ah, al		; save that setting
  2199 00001482 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2200 00001484 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2201                              <1> 	;popf	; 18/01/2014
  2202 00001486 FB                  <1> 	sti
  2203                              <1> g7:				; 1/64 second per count (bl)
  2204 00001487 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2205 0000148C E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2206 00001491 FECB                <1> 	dec	bl		; (bl) length count expired?
  2207 00001493 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2208                              <1> 	;
  2209                              <1> 	;pushf			; save interrupt status
  2210 00001495 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2211 00001496 E461                <1> 	in	al, PORT_B	; get current port value
  2212                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2213 00001498 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2214 0000149A 20C4                <1>         and	ah, al		; someone turned them off during beep
  2215 0000149C 88E0                <1> 	mov	al, ah		; recover value of port
  2216                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2217 0000149E 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2218 000014A0 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2219                              <1> 	;popf			; restore interrupt flag state
  2220 000014A2 FB                  <1> 	sti
  2221 000014A3 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2222 000014A8 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2223                              <1> 	;pushf			; save interrupt status
  2224 000014AD FA                  <1> 	cli			; block interrupts during update
  2225 000014AE E461                <1> 	in	al, PORT_B	; get current port value in case	
  2226 000014B0 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2227 000014B2 08E0                <1> 	or	al, ah		; recover value of port_b
  2228 000014B4 E661                <1> 	out	PORT_B, al	; restore speaker status
  2229 000014B6 9D                  <1> 	popf			; restore interrupt flag state
  2230                              <1> u12:	
  2231 000014B7 C3                  <1> 	retn
  2232                              <1> 
  2233                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2234                              <1> 
  2235                              <1> WAITF:
  2236                              <1> waitf:
  2237                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2238                              <1> 	; 03/12/2013
  2239                              <1> 	;
  2240                              <1> ;	push	ax		; save work register (ah)	
  2241                              <1> ;waitf1:
  2242                              <1> 				; use timer 1 output bits
  2243                              <1> ;	in	al, PORT_B	; read current counter output status
  2244                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2245                              <1> ;	cmp	al, ah		; did it just change
  2246                              <1> ;	je	short waitf1	; wait for a change in output line
  2247                              <1> ;	;
  2248                              <1> ;	mov	ah, al		; save new lflag state
  2249                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2250                              <1> ;	;
  2251                              <1> ;	pop	ax		; restore (ah)
  2252                              <1> ;	retn			; return (cx)=0
  2253                              <1> 
  2254                              <1> ; 02/02/2022
  2255                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2256                              <1> ; 17/12/2014 (dsectrm2.s)
  2257                              <1> ; WAITF
  2258                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2259                              <1> ;
  2260                              <1> ;---WAITF-----------------------------------------------------------------------
  2261                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2262                              <1> ; ENTRY:
  2263                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2264                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2265                              <1> ; EXIT:
  2266                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2267                              <1> ;	(CX) = 0	
  2268                              <1> ;-------------------------------------------------------------------------------
  2269                              <1> 
  2270                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2271                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2272                              <1> 
  2273                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2274 000014B8 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2275                              <1> 	;push	ax
  2276                              <1> 	; 16/12/2014
  2277                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2278 000014B9 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2279                              <1> ;17/12/2014	
  2280                              <1> ;WAITF1:
  2281                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2282                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2283                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2284                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2285                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2286                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2287                              <1> 	;
  2288                              <1> 	; 17/12/2014
  2289                              <1> 	;
  2290                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2291                              <1> 	;
  2292                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2293                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2294                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2295                              <1> WR_STATE_0:
  2296 000014BB E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2297 000014BD A810                <1> 	TEST	AL,010H
  2298 000014BF 74FA                <1> 	JZ	SHORT WR_STATE_0
  2299                              <1> WR_STATE_1:
  2300 000014C1 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2301 000014C3 A810                <1> 	TEST	AL,010H
  2302 000014C5 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2303 000014C7 E2F2                <1>         LOOP    WR_STATE_0
  2304                              <1> 	;
  2305                              <1> 	;pop	ax
  2306 000014C9 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2307 000014CA C3                  <1> 	RETn				; (CX) = 0
  2308                              <1> 
  2309                              <1> set_cpos:
  2310                              <1> 	; 14/06/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.4)
  2311                              <1> 	; 26/02/2022
  2312                              <1> 	; 02/02/2022
  2313                              <1> 	; 27/06/2015
  2314                              <1> 	; 01/09/2014
  2315                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2316                              <1> 	;
  2317                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2318                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2319                              <1> 	;
  2320                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2321                              <1> 	;
  2322                              <1> 	; SET_CPOS
  2323                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2324                              <1> 	;	NEW X-Y VALUES PASSED
  2325                              <1> 	; INPUT
  2326                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2327                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2328                              <1> 	; OUTPUT
  2329                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2330                              <1> 	;
  2331 000014CB 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2332 000014CE D0E0                <1>         shl     al, 1   ; word offset
  2333 000014D0 BE[F6640000]        <1> 	mov	esi, cursor_posn
  2334 000014D5 01C6                <1>         add     esi, eax
  2335 000014D7 668916              <1> 	mov	[esi], dx ; save the pointer
  2336 000014DA 381D[06650000]      <1> 	cmp	[active_page], bl
  2337 000014E0 7531                <1> 	jne	short m17
  2338                              <1> 
  2339                              <1> 	; 14/06/2022
  2340                              <1> 	;cli ; 26/02/2022
  2341                              <1> 
  2342                              <1> 	;call	m18	;h CURSOR SET
  2343                              <1> ;m17:			; SET_CPOS_RETURN
  2344                              <1> 	; 01/09/2014
  2345                              <1> 	;retn
  2346                              <1> 		; DX = row/column
  2347                              <1> m18:
  2348 000014E2 E832000000          <1> 	call	position ; determine location in regen buffer	
  2349                              <1> 	;mov	cx, [CRT_START]
  2350                              <1> 	; 26/02/2022
  2351 000014E7 0FB70D[F4640000]    <1> 	movzx	ecx, word [CRT_START]
  2352 000014EE 01C1                <1> 	add	ecx, eax
  2353                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2354                              <1> 			; to the start address (offset) for this page
  2355                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2356                              <1> 	; 26/02/2022
  2357 000014F0 D1E9                <1> 	shr	ecx, 1
  2358 000014F2 B40E                <1> 	mov	ah, 14	; register number for cursor
  2359                              <1> 	
  2360                              <1> 	; 14/06/2022
  2361                              <1> 	;call	m16	; output value to the 6845
  2362                              <1> 	;sti	; 26/02/2022
  2363                              <1> 	;retn
  2364                              <1> 
  2365                              <1> 	; 14/06/2022
  2366                              <1> 	; 26/02/2022
  2367                              <1> 	; 02/02/2022
  2368                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2369                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2370                              <1> m16:
  2371                              <1> 	; 14/06/2022
  2372 000014F4 FA                  <1> 	cli	; 26/02/2022
  2373                              <1> 	;mov	dx, [addr_6845] ; address register
  2374 000014F5 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2375 000014F9 88E0                <1> 	mov	al, ah	; get value
  2376 000014FB EE                  <1> 	out	dx, al	; register set
  2377                              <1> 	;inc	dx	; data register
  2378                              <1> 	; 02/02/2022
  2379 000014FC FEC2                <1> 	inc	dl
  2380 000014FE EB00                <1> 	jmp	$+2	; i/o delay
  2381 00001500 88E8                <1> 	mov	al, ch	; data
  2382 00001502 EE                  <1> 	out	dx, al	
  2383                              <1> 	;dec	dx
  2384                              <1> 	; 02/02/2022	
  2385 00001503 FECA                <1> 	dec	dl
  2386 00001505 88E0                <1> 	mov	al, ah
  2387 00001507 FEC0                <1> 	inc	al	; point to other data register
  2388 00001509 EE                  <1> 	out	dx, al	; set for second register
  2389                              <1> 	;inc	dx
  2390                              <1> 	; 02/02/2022
  2391 0000150A FEC2                <1> 	inc	dl
  2392 0000150C EB00                <1> 	jmp	$+2	; i/o delay
  2393 0000150E 88C8                <1> 	mov	al, cl	; second data value
  2394 00001510 EE                  <1> 	out	dx, al
  2395                              <1> 	; 14/06/2022
  2396 00001511 FB                  <1> 	sti	; 26/02/2022
  2397                              <1> ;m17:
  2398 00001512 C3                  <1> 	retn
  2399                              <1> m17:
  2400                              <1> 	; 14/06/2022
  2401                              <1> 	; ('write_tty' must not return to 'putc'/'wtty' with cf)
  2402 00001513 F8                  <1> 	clc
  2403 00001514 C3                  <1> 	retn
  2404                              <1> 
  2405                              <1> set_ctype:
  2406                              <1> 	; 07/02/2022
  2407                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2408                              <1> 	;
  2409                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2410                              <1> 
  2411                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2412                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2413                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2414                              <1> ;          OR NO CURSOR AT ALL
  2415                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2416                              <1> 
  2417                              <1> ;------------------------------------------------
  2418                              <1> ; SET_CTYPE
  2419                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2420                              <1> ; INPUT
  2421                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2422                              <1> ; OUTPUT	
  2423                              <1> ;	NONE
  2424                              <1> ;------------------------------------------------
  2425                              <1> 
  2426 00001515 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2427                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2428                              <1> 	;call	m16	; output cx register
  2429                              <1> 	;retn
  2430                              <1> 	; 07/02/2022
  2431 00001517 EBDB                <1> 	jmp	short m16
  2432                              <1> 
  2433                              <1> position:
  2434                              <1> 	; 26/02/2022
  2435                              <1> 	; 02/02/2022
  2436                              <1> 	; 27/06/2015
  2437                              <1> 	; 02/09/2014
  2438                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2439                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2440                              <1> 	;
  2441                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2442                              <1> 	;
  2443                              <1> 	; POSITION
  2444                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2445                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2446                              <1> 	; INPUT
  2447                              <1> 	;	AX = ROW, COLUMN POSITION
  2448                              <1> 	; OUTPUT
  2449                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2450                              <1> 
  2451                              <1> 		; DX = ROW, COLUMN POSITION
  2452                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2453 00001519 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2454 0000151B B050                <1> 	mov	al, 80	; determine bytes to row	
  2455 0000151D F6E6                <1> 	mul	dh	; row value
  2456                              <1> 	;xor	dh, dh	; 0
  2457                              <1> 	;add	ax, dx	; add column value to the result
  2458                              <1> 	; 26/02/2022
  2459 0000151F 00D0                <1> 	add	al, dl
  2460 00001521 80D400              <1> 	adc	ah, 0	
  2461                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2462                              <1> 	; 02/02/2022
  2463 00001524 D1E0                <1> 	shl	eax, 1
  2464                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2465 00001526 C3                  <1> 	retn
  2466                              <1> 
  2467                              <1> find_position:
  2468                              <1> 	; 02/02/2022
  2469                              <1> 	; 27/06/2015
  2470                              <1> 	; 07/09/2014
  2471                              <1> 	; 02/09/2014
  2472                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2473                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2474 00001527 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2475 0000152A 89CE                <1> 	mov	esi, ecx
  2476                              <1> 	;shl	si, 1
  2477                              <1> 	; 02/02/2022
  2478 0000152C D1E6                <1> 	shl	esi, 1
  2479 0000152E 668B96[F6640000]    <1> 	mov	dx, [esi+cursor_posn]
  2480 00001535 7409                <1> 	jz	short p21
  2481                              <1> 	;xor	si, si
  2482                              <1> 	; 02/02/2022
  2483 00001537 31F6                <1> 	xor	esi, esi
  2484                              <1> p20:
  2485                              <1> 	;add	si, [CRT_LEN]
  2486 00001539 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2487 0000153E E2F9                <1> 	loop	p20
  2488                              <1> p21:
  2489 00001540 6621D2              <1> 	and	dx, dx
  2490 00001543 7407                <1> 	jz	short p22
  2491 00001545 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2492 0000154A 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2493                              <1> p22:	
  2494                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2495                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2496                              <1> 	;add	dx, 6	; point at status port
  2497 0000154C 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2498                              <1> 	; cx = 0
  2499 00001550 C3                  <1> 	retn
  2500                              <1> 
  2501                              <1> scroll_up:
  2502                              <1> 	; 02/02/2022 (simplified scroll up)
  2503                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2504                              <1> 	; 16/01/2016
  2505                              <1> 	; 07/09/2014
  2506                              <1> 	; 02/09/2014
  2507                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2508                              <1> 	; 04/04/2014
  2509                              <1> 	; 04/12/2013
  2510                              <1> 	;
  2511                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2512                              <1> 	;
  2513                              <1> 	; SCROLL UP
  2514                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2515                              <1> 	;	ON THE SCREEN
  2516                              <1> 	; INPUT
  2517                              <1> 	;	(AH) = CURRENT CRT MODE
  2518                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2519                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2520                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2521                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2522                              <1> 	;	(DS) = DATA SEGMENT
  2523                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2524                              <1> 	; OUTPUT
  2525                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2526                              <1> 	;
  2527                              <1> 	;	bh = 0  (02/09/2014)
  2528                              <1> 	;
  2529                              <1> 	; ((ah = 3))
  2530                              <1> 	; cl = left upper column
  2531                              <1> 	; ch = left upper row
  2532                              <1> 	; dl = right lower column
  2533                              <1> 	; dh = right lower row
  2534                              <1> 	;
  2535                              <1> 	; al = line count 
  2536                              <1> 	; ah = attribute to be used on blanked line
  2537                              <1> 	; bl = video page number (0 to 7)
  2538                              <1> 	; 
  2539                              <1> 
  2540                              <1> 	; 02/02/2022 'scroll_up' code
  2541                              <1> 	; ------------------------------------------------------
  2542                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2543                              <1> 
  2544                              <1> 	; INPUT:
  2545                              <1> 	;		
  2546                              <1> 	; al = line count 
  2547                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2548                              <1> 	; ah = attribute to be used on blanked line
  2549                              <1> 	; bl = video page number (0 to 7)
  2550                              <1> 
  2551                              <1> 	;cli
  2552 00001551 31C9                <1> 	xor	ecx, ecx
  2553 00001553 88C1                <1> 	mov	cl, al ; line count (cl)
  2554 00001555 BE00800B00          <1> 	mov	esi, 0B8000h
  2555 0000155A 3A1D[06650000]      <1> 	cmp	bl, [active_page]
  2556 00001560 7411                <1> 	je	short n1
  2557 00001562 20DB                <1> 	and	bl, bl
  2558 00001564 7422                <1> 	jz	short n3
  2559 00001566 88DD                <1> 	mov	ch, bl ; video page number
  2560                              <1> n0:
  2561 00001568 6681C6A00F          <1> 	add	si, 25*80*2
  2562 0000156D FECD                <1> 	dec	ch
  2563 0000156F 75F7                <1> 	jnz	short n0
  2564 00001571 EB15                <1> 	jmp	short n3
  2565                              <1> n1:
  2566 00001573 660335[F4640000]    <1> 	add	si, [CRT_START]
  2567                              <1> 	;
  2568 0000157A 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2569                              <1> n2:			 ; wait_display_enable
  2570 0000157E EC                  <1> 	in	al, dx	 ; get port
  2571 0000157F A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2572 00001581 74FB                <1> 	jz	short n2 ; wait_display_enable
  2573 00001583 B025                <1> 	mov	al, 25h
  2574 00001585 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2575 00001587 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2576                              <1> n3:
  2577                              <1> 	; cl = line count
  2578                              <1> 	; ah = attribute/color
  2579 00001588 89F7                <1> 	mov	edi, esi
  2580 0000158A 20C9                <1> 	and	cl, cl
  2581 0000158C 741F                <1> 	jz	short n6
  2582 0000158E 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2583 00001593 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2584 00001597 F366A5              <1> 	rep	movsw
  2585 0000159A B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2586                              <1> n4:
  2587                              <1> 	; ah = character attribute/cocor
  2588 0000159C B020                <1> 	mov	al, 20h ; fill with blanks
  2589 0000159E F366AB              <1> 	rep	stosw
  2590                              <1> 
  2591 000015A1 3A1D[06650000]      <1> 	cmp	bl, [active_page]
  2592 000015A7 7503                <1> 	jne	short n5
  2593                              <1> 
  2594                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2595 000015A9 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
  2596                              <1> 	;mov	dx, 03D8h ; always set color card port
  2597 000015AB EE                  <1> 	out	dx, al
  2598                              <1> n5:
  2599 000015AC C3                  <1> 	retn
  2600                              <1> n6:
  2601                              <1> 	; clear video page
  2602 000015AD 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2603 000015B1 EBE9                <1> 	jmp	short n4
  2604                              <1> 
  2605                              <1> 	; 26/02/2022
  2606                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2607                              <1> 	; ------------------------------------------------------
  2608                              <1> 
  2609                              <1> 	; Test	Line Count
  2610                              <1> 	or	al, al
  2611                              <1> 	jz	short al_set
  2612                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2613                              <1> 	sub	bh, ch
  2614                              <1> 	inc	bh	; adjust difference by 1
  2615                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2616                              <1> 	jne	short al_set ; if not the we're all set
  2617                              <1> 	xor	al, al	; otherwise set al to zero
  2618                              <1> al_set:
  2619                              <1> 	xor	bh, bh	; 0
  2620                              <1> 	;push	ax
  2621                              <1> 	push	eax ; 26/02/2022
  2622                              <1> 	;mov 	esi, [crt_base]
  2623                              <1>         mov     esi, 0B8000h  
  2624                              <1>         cmp     bl, [active_page]
  2625                              <1> 	jne	short n0
  2626                              <1> 	;
  2627                              <1>         mov     ax, [CRT_START]
  2628                              <1>         add     si, ax
  2629                              <1>         jmp     short n1
  2630                              <1> n0:
  2631                              <1>         and     bl, bl
  2632                              <1> 	jz	short n1
  2633                              <1> 	mov	al, bl
  2634                              <1> n0x:
  2635                              <1>         ;add    si, [CRT_LEN]
  2636                              <1>         ;add    esi, 80*25*2 
  2637                              <1>         add     si, 80*25*2
  2638                              <1>         dec	al
  2639                              <1> 	jnz	short n0x
  2640                              <1> n1:	
  2641                              <1>         ; Scroll position
  2642                              <1> 	;push	dx ; 26/02/2022
  2643                              <1> 	mov	dx, cx	; now, upper left position in DX
  2644                              <1> 	call	position
  2645                              <1> 	add	esi, eax
  2646                              <1> 	mov	edi, esi
  2647                              <1> 	;pop	dx	; lower right position in DX
  2648                              <1> 	sub	dx, cx
  2649                              <1> 	inc	dh	; dh = #rows 
  2650                              <1> 	inc	dl	; dl = #cols in block
  2651                              <1> 	;pop	ax	; al = line count, ah = attribute
  2652                              <1> 	pop	eax ; 26/02/2022
  2653                              <1> 	xor	ecx, ecx
  2654                              <1> 	mov	cx, ax
  2655                              <1> 	;mov	ah, [CRT_COLS]
  2656                              <1> 	mov	ah, 80
  2657                              <1> 	mul	ah	; determine offset to from address
  2658                              <1> 	add	ax, ax  ; *2 for attribute byte
  2659                              <1> 	;
  2660                              <1> 	;push	ax	; offset 
  2661                              <1> 	;push	dx
  2662                              <1> 	; 26/02/2022
  2663                              <1> 	push	eax
  2664                              <1> 	push	edx
  2665                              <1> 	;
  2666                              <1> 	; 04/04/2014
  2667                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2668                              <1> n8:                      ; wait_display_enable
  2669                              <1>         in      al, dx   ; get port
  2670                              <1> 	test	al, RVRT ; wait for vertical retrace
  2671                              <1> 	jz	short n8 ; wait_display_enable
  2672                              <1> 	mov	al, 25h
  2673                              <1> 	mov	dl, 0D8h ; address control port
  2674                              <1> 	out	dx, al	; turn off video during vertical retrace
  2675                              <1> 	;pop	dx	; #rows, #cols
  2676                              <1>        	;pop	ax	; offset
  2677                              <1> 	; 26/02/2022
  2678                              <1> 	pop	edx
  2679                              <1> 	pop	eax
  2680                              <1> 	xchg	ax, cx	; 
  2681                              <1> 	; ecx = offset, al = line count, ah = attribute
  2682                              <1> ;n9:
  2683                              <1> 	or	al, al
  2684                              <1>         jz      short n3 
  2685                              <1>         add     esi, ecx ; from address for scroll
  2686                              <1> 	mov	bh, dh  ; #rows in block
  2687                              <1> 	sub	bh, al	; #rows to be moved
  2688                              <1> n2:
  2689                              <1> 	; Move rows
  2690                              <1> 	mov	cl, dl	; get # of cols to move
  2691                              <1> 	push	esi
  2692                              <1> 	push	edi	; save start address
  2693                              <1> n10:
  2694                              <1> 	movsw		; move that line on screen
  2695                              <1> 	dec	cl
  2696                              <1>         jnz     short n10
  2697                              <1> 	pop	edi
  2698                              <1> 	pop	esi	; recover addresses
  2699                              <1>         ;mov    cl, [CRT_COLS] 
  2700                              <1> 	;add	cl, cl
  2701                              <1>         ;mov    ecx, 80*2
  2702                              <1>         mov     cx, 80*2
  2703                              <1>         add     esi, ecx  ; next line
  2704                              <1>         add     edi, ecx
  2705                              <1> 	dec	bh	 ; count of lines to move
  2706                              <1> 	jnz	short n2 ; row loop
  2707                              <1> 	; bh = 0
  2708                              <1> 	mov	dh, al	 ; #rows	
  2709                              <1> n3:
  2710                              <1> 	; attribute in ah
  2711                              <1> 	mov	al, ' '	 ; fill with blanks
  2712                              <1> n3x:
  2713                              <1> 	; Clear rows
  2714                              <1>                 ; dh =  #rows
  2715                              <1>         mov	cl, dl	; get # of cols to clear
  2716                              <1>         push    edi     ; save address
  2717                              <1> n11:
  2718                              <1>         stosw           ; store fill character
  2719                              <1> 	dec	cl
  2720                              <1>         jnz     short n11
  2721                              <1>         pop     edi     ; recover address
  2722                              <1> 	;mov	cl, [CRT_COLS]
  2723                              <1> 	;add	cl, cl
  2724                              <1>         ;mov    ecx, 80*2
  2725                              <1>         mov	cl, 80*2
  2726                              <1>         add     edi, ecx
  2727                              <1> 	dec	dh
  2728                              <1> 	jnz	short n3x ; 16/01/2016
  2729                              <1> 	;
  2730                              <1> 	cmp	bl, [active_page]
  2731                              <1> 	jne	short n6
  2732                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2733                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2734                              <1> 	mov	dx, 03D8h ; always set color card port
  2735                              <1> 	out	dx, al
  2736                              <1> n6:
  2737                              <1> 	retn
  2738                              <1> 
  2739                              <1> %endif
  2740                              <1> 
  2741                              <1> write_c_current:
  2742                              <1> 	; 02/02/2022
  2743                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2744                              <1> 	; 18/01/2014
  2745                              <1> 	; 04/12/2013
  2746                              <1> 	;
  2747                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2748                              <1> 	;
  2749                              <1> 	; WRITE_C_CURRENT
  2750                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2751                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2752                              <1> 	; INPUT	
  2753                              <1> 	;	(AH) = CURRENT CRT MODE
  2754                              <1> 	;	(BH) = DISPLAY PAGE
  2755                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2756                              <1> 	;	(AL) = CHAR TO WRITE
  2757                              <1> 	;	(DS) = DATA SEGMENT
  2758                              <1> 	;	(ES) = REGEN SEGMENT
  2759                              <1> 	; OUTPUT
  2760                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2761                              <1> 
  2762 000015B3 FA                  <1> 	cli		
  2763                              <1> 	; bl = video page
  2764                              <1> 	; al = character
  2765                              <1> 	; ah = color/attribute
  2766                              <1> 	;push	dx
  2767                              <1> 	;push	ax	; save character & attribute/color
  2768                              <1> 	; 02/02/2022
  2769 000015B4 52                  <1> 	push	edx
  2770 000015B5 50                  <1> 	push	eax
  2771 000015B6 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2772                              <1> 	; esi = regen location
  2773                              <1> 	; dx = status port
  2774                              <1> 	;
  2775                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2776                              <1> 	;
  2777                              <1> p41:			; wait for horizontal retrace is low or vertical
  2778 000015BB FB                  <1> 	sti		; enable interrupts first
  2779 000015BC 3A1D[06650000]      <1>         cmp     bl, [active_page]
  2780 000015C2 7510                <1> 	jne	short p44 
  2781 000015C4 FA                  <1> 	cli 		; block interrupts for single loop
  2782 000015C5 EC                  <1> 	in	al, dx	; get status from the adapter
  2783 000015C6 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2784 000015C8 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2785 000015CA A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2786 000015CC 75ED                <1> 	jnz	short p41 ; wait until it is
  2787                              <1> p42:			; wait for either retrace high
  2788 000015CE EC                  <1> 	in	al, dx	; get status again
  2789 000015CF A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2790 000015D1 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2791                              <1> p43:	
  2792 000015D3 FB                  <1> 	sti
  2793                              <1> p44:
  2794                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2795                              <1> 	; 02/02/2022
  2796 000015D4 58                  <1> 	pop	eax
  2797 000015D5 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2798                              <1> 			; Retro UNIX 386 v1 feature only!
  2799 000015DB 668906              <1> 	mov	[esi], ax
  2800                              <1> 	;pop	dx
  2801                              <1> 	; 02/02/2022
  2802 000015DE 5A                  <1> 	pop	edx
  2803 000015DF C3                  <1> 	retn
  2804                              <1> 
  2805                              <1> %if 0	; 02/02/2022
  2806                              <1> 
  2807                              <1> set_mode:
  2808                              <1> 	; 02/02/2022
  2809                              <1> 	; 16/01/2016
  2810                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2811                              <1> 	;
  2812                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2813                              <1> 
  2814                              <1> ;------------------------------------------------------
  2815                              <1> ; SET MODE					      :
  2816                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2817                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2818                              <1> ; INPUT						      :
  2819                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2820                              <1> ; OUTPUT					      :
  2821                              <1> ;	NONE					      :
  2822                              <1> ;------------------------------------------------------
  2823                              <1> 
  2824                              <1> 	push	edi ; 16/01/2016
  2825                              <1> 	push	ebx
  2826                              <1> 	push	edx
  2827                              <1> 	push	ecx ; 16/01/2016
  2828                              <1>         push    eax
  2829                              <1> 
  2830                              <1> 	;mov	dx, 03D4h 	; address or color card
  2831                              <1> 	mov	al, 3
  2832                              <1> ;M8:
  2833                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2834                              <1> 	mov	al, 29h
  2835                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2836                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2837                              <1> 	;push	dx  		; save port value
  2838                              <1> 	;add	dx, 4		; point to control register
  2839                              <1> 	mov	dx, 3D8h
  2840                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2841                              <1> 	;pop	dx
  2842                              <1> ;M9:
  2843                              <1> 	mov	ebx, video_params ; initialization table
  2844                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2845                              <1> 	;xchg 	ah, al
  2846                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2847                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2848                              <1> 	
  2849                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2850                              <1> 	; 02/02/2022
  2851                              <1> 	; dx = 3D8h
  2852                              <1> 	xor	ecx, ecx
  2853                              <1> 	mov	cl, 16
  2854                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2855                              <1> M10:			;  initialization loop
  2856                              <1> 	mov	al, ah 	; get 6845 register number
  2857                              <1> 	out	dx, al
  2858                              <1> 	;inc	dx      ; point to data port
  2859                              <1> 	; 02/02/2022
  2860                              <1> 	inc	dl ; 3D9h
  2861                              <1> 	inc	ah	; next register value
  2862                              <1> 	mov	al, [ebx] ; get table value
  2863                              <1> 	out	dx, al	; out to chip
  2864                              <1> 	inc	ebx	; next in table
  2865                              <1> 	;dec	dx	; back to pointer register
  2866                              <1> 	; 02/02/2022
  2867                              <1> 	dec	dl ; 3D8h
  2868                              <1> 	loop	M10	; do the whole table
  2869                              <1> 	
  2870                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2871                              <1> 	;xor	ax, ax  
  2872                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2873                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2874                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2875                              <1> 	; black background, light gray characeter color, space character
  2876                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2877                              <1> ;M13:			  ; clear buffer
  2878                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2879                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2880                              <1> 
  2881                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2882                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2883                              <1> 			 ; prepare to output to video enable port
  2884                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2885                              <1> 	; 02/02/2022
  2886                              <1> 	;mov	dx, 3D8h
  2887                              <1> 	; 
  2888                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2889                              <1> 	mov	al, 29h
  2890                              <1> 	out	dx, al	 ; set video enable port
  2891                              <1> 
  2892                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2893                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2894                              <1> 	;
  2895                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2896                              <1> 	;
  2897                              <1> ;-----	SET CURSOR POSITIONS
  2898                              <1> 	;push	edi
  2899                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2900                              <1> 	mov	edi, cursor_posn
  2901                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2902                              <1> 	xor	eax, eax
  2903                              <1> 	rep 	stosd	; fill with zeroes
  2904                              <1> 	;pop	edi
  2905                              <1> 
  2906                              <1> ;-----	SET UP OVERSCAN REGISTER
  2907                              <1> 	inc	dx	; set overscan port to a default
  2908                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2909                              <1> ;M14:
  2910                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2911                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2912                              <1> 
  2913                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2914                              <1> 	;
  2915                              <1> 	pop	eax
  2916                              <1> 	pop	ecx ; 16/01/2016
  2917                              <1> 	pop	edx
  2918                              <1> 	pop	ebx
  2919                              <1> 	pop	edi ; 16/01/2016
  2920                              <1> 	retn
  2921                              <1> 
  2922                              <1> %endif
  2923                              <1> 	
  2924                              <1> tty_sw:
  2925                              <1> 	; 02/02/2022
  2926                              <1> 	; 30/06/2015
  2927                              <1> 	; 27/06/2015 
  2928                              <1> 	; 07/09/2014
  2929                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2930                              <1> 	;
  2931                              <1> 	; (Modified registers : EAX)
  2932                              <1> 	;
  2933                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2934                              <1> 	;
  2935                              <1> ;act_disp_page:
  2936                              <1> 	; 30/06/2015
  2937                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2938                              <1> 	; 10/12/2013
  2939                              <1> 	; 04/12/2013
  2940                              <1> 	;
  2941                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2942                              <1> 	;
  2943                              <1> 	; ACT_DISP_PAGE
  2944                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2945                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2946                              <1> 	; INPUT
  2947                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2948                              <1> 	; OUTPUT
  2949                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2950                              <1> 
  2951                              <1> 	;cli
  2952                              <1> 
  2953 000015E0 53                  <1> 	push	ebx
  2954                              <1> 	;push	cx
  2955                              <1> 	;push	dx
  2956                              <1> 	; 02/02/2022
  2957 000015E1 51                  <1> 	push	ecx
  2958 000015E2 52                  <1> 	push	edx
  2959                              <1> 	;
  2960 000015E3 A2[06650000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2961                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2962                              <1> 	;mov	cx, 25*80*2
  2963                              <1> 	; 02/02/2022
  2964 000015E8 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2965                              <1> 	; 27/06/2015
  2966 000015ED 0FB6D8              <1> 	movzx	ebx, al
  2967                              <1> 	; 02/02/2022
  2968 000015F0 89D8                <1> 	mov	eax, ebx
  2969                              <1> 	;
  2970                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2971                              <1> 	;mul 	cx	; display page times regen length
  2972                              <1> 	; 02/02/2022
  2973 000015F2 F7E1                <1> 	mul	ecx	
  2974                              <1> 	; 10/12/2013
  2975 000015F4 66A3[F4640000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2976                              <1> 	;mov	cx, ax	; start address to cx
  2977                              <1> 	; 02/02/2022
  2978 000015FA 89C1                <1> 	mov	ecx, eax
  2979                              <1> 	;sar	cx, 1
  2980                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2981                              <1> 	; 02/02/2022
  2982 000015FC D1E9                <1> 	shr	ecx, 1
  2983 000015FE B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2984 00001600 E8EFFEFFFF          <1> 	call	m16
  2985                              <1> 	;sal	bx, 1
  2986                              <1> 	; 01/09/2014
  2987 00001605 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2988 00001607 81C3[F6640000]      <1> 	add	ebx, cursor_posn
  2989 0000160D 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2990 00001610 E8CDFEFFFF          <1> 	call	m18
  2991                              <1> 	;
  2992                              <1> 	;pop	dx
  2993                              <1> 	;pop	cx
  2994                              <1> 	; 02/02/2022
  2995 00001615 5A                  <1> 	pop	edx
  2996 00001616 59                  <1> 	pop	ecx
  2997 00001617 5B                  <1> 	pop	ebx
  2998                              <1> 	;
  2999                              <1> 	;sti
  3000                              <1> 	;
  3001 00001618 C3                  <1> 	retn
  3002                              <1> 
  3003                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  3004                              <1> 
  3005                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1885                                  
  1886                                  setup_rtc_int:
  1887                                  ; source: http://wiki.osdev.org/RTC
  1888 00001619 FA                      	cli		; disable interrupts
  1889                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1890                                  	; in order to change this ...
  1891                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1892                                  	; (rate must be above 2 and not over 15)
  1893                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1894 0000161A B08A                    	mov	al, 8Ah 
  1895 0000161C E670                    	out	70h, al ; set index to register A, disable NMI
  1896 0000161E 90                      	nop
  1897 0000161F E471                    	in	al, 71h ; get initial value of register A
  1898 00001621 88C4                    	mov 	ah, al
  1899 00001623 80E4F0                  	and	ah, 0F0h
  1900 00001626 B08A                    	mov	al, 8Ah 
  1901 00001628 E670                    	out	70h, al ; reset index to register A
  1902 0000162A 88E0                    	mov	al, ah
  1903 0000162C 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1904 0000162E E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1905                                  	; enable RTC interrupt
  1906 00001630 B08B                    	mov	al, 8Bh ;
  1907 00001632 E670                    	out	70h, al ; select register B and disable NMI
  1908 00001634 90                      	nop
  1909 00001635 E471                    	in	al, 71h ; read the current value of register B
  1910 00001637 88C4                    	mov	ah, al  ;
  1911 00001639 B08B                    	mov 	al, 8Bh ;
  1912 0000163B E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1913 0000163D 88E0                    	mov	al, ah  ;
  1914 0000163F 0C40                    	or	al, 40h ;
  1915 00001641 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1916 00001643 FB                      	sti
  1917 00001644 C3                      	retn
  1918                                  
  1919                                  ; Write memory information
  1920                                  ; Temporary Code
  1921                                  ; 06/11/2014
  1922                                  ; 14/08/2015 
  1923                                  memory_info:	
  1924 00001645 A1[DC640000]            	mov	eax, [memory_size] ; in pages
  1925 0000164A 50                      	push	eax
  1926 0000164B C1E00C                  	shl	eax, 12		   ; in bytes
  1927 0000164E BB0A000000              	mov	ebx, 10
  1928 00001653 89D9                    	mov	ecx, ebx	   ; 10
  1929 00001655 BE[41610000]            	mov	esi, mem_total_b_str	
  1930 0000165A E8AE000000              	call	bintdstr
  1931 0000165F 58                      	pop	eax
  1932 00001660 B107                    	mov	cl, 7
  1933 00001662 BE[65610000]            	mov	esi, mem_total_p_str
  1934 00001667 E8A1000000              	call	bintdstr	
  1935                                  	; 14/08/2015
  1936 0000166C E8B9000000              	call	calc_free_mem
  1937                                  	; edx = calculated free pages
  1938                                  	; ecx = 0
  1939 00001671 A1[E0640000]            	mov 	eax, [free_pages]
  1940 00001676 39D0                    	cmp	eax, edx ; calculated free mem value 
  1941                                  		; and initial free mem value are same or not?
  1942 00001678 751D                    	jne 	short pmim ; print mem info with '?' if not
  1943 0000167A 52                      	push 	edx ; free memory in pages	
  1944                                  	;mov 	eax, edx
  1945 0000167B C1E00C                  	shl	eax, 12 ; convert page count
  1946                                  			; to byte count
  1947 0000167E B10A                    	mov	cl, 10
  1948 00001680 BE[85610000]            	mov	esi, free_mem_b_str
  1949 00001685 E883000000              	call	bintdstr
  1950 0000168A 58                      	pop	eax
  1951 0000168B B107                    	mov	cl, 7
  1952 0000168D BE[A9610000]            	mov	esi, free_mem_p_str
  1953 00001692 E876000000              	call	bintdstr
  1954                                  pmim:
  1955 00001697 BE[2F610000]            	mov	esi, msg_memory_info
  1956                                  pmim_nb:	
  1957 0000169C AC                      	lodsb
  1958 0000169D 08C0                    	or	al, al
  1959 0000169F 740D                    	jz	short pmim_ok
  1960 000016A1 56                      	push	esi
  1961 000016A2 31DB                    	xor	ebx, ebx ; 0
  1962                                  			; Video page 0 (bl=0)
  1963 000016A4 B407                    	mov	ah, 07h ; Black background, 
  1964                                  			; light gray forecolor
  1965 000016A6 E816FDFFFF              	call	write_tty
  1966 000016AB 5E                      	pop	esi
  1967 000016AC EBEE                    	jmp	short pmim_nb
  1968                                  pmim_ok:
  1969 000016AE C3                      	retn
  1970                                  
  1971                                  ; Convert binary number to hexadecimal string
  1972                                  ; 10/05/2015  
  1973                                  ; dsectpm.s (28/02/2015)
  1974                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1975                                  ; 01/12/2014
  1976                                  ; 25/11/2014
  1977                                  ;
  1978                                  bytetohex:
  1979                                  	; INPUT ->
  1980                                  	; 	AL = byte (binary number)
  1981                                  	; OUTPUT ->
  1982                                  	;	AX = hexadecimal string
  1983                                  	;
  1984 000016AF 53                      	push	ebx
  1985 000016B0 31DB                    	xor	ebx, ebx
  1986 000016B2 88C3                    	mov	bl, al
  1987 000016B4 C0EB04                  	shr	bl, 4
  1988 000016B7 8A9B[FD160000]          	mov	bl, [ebx+hexchrs]
  1989 000016BD 86D8                    	xchg	bl, al
  1990 000016BF 80E30F                  	and	bl, 0Fh
  1991 000016C2 8AA3[FD160000]          	mov	ah, [ebx+hexchrs]
  1992 000016C8 5B                      	pop	ebx	
  1993 000016C9 C3                      	retn
  1994                                  
  1995                                  wordtohex:
  1996                                  	; INPUT ->
  1997                                  	; 	AX = word (binary number)
  1998                                  	; OUTPUT ->
  1999                                  	;	EAX = hexadecimal string
  2000                                  	;
  2001 000016CA 53                      	push	ebx
  2002 000016CB 31DB                    	xor	ebx, ebx
  2003 000016CD 86E0                    	xchg	ah, al
  2004 000016CF 6650                    	push	ax
  2005 000016D1 88E3                    	mov	bl, ah
  2006 000016D3 C0EB04                  	shr	bl, 4
  2007 000016D6 8A83[FD160000]          	mov	al, [ebx+hexchrs]
  2008 000016DC 88E3                    	mov	bl, ah
  2009 000016DE 80E30F                  	and	bl, 0Fh
  2010 000016E1 8AA3[FD160000]          	mov	ah, [ebx+hexchrs]
  2011 000016E7 C1E010                  	shl	eax, 16
  2012 000016EA 6658                    	pop	ax
  2013 000016EC 5B                      	pop	ebx
  2014 000016ED EBC0                    	jmp	short bytetohex
  2015                                  	;mov	bl, al
  2016                                  	;shr	bl, 4
  2017                                  	;mov	bl, [ebx+hexchrs]
  2018                                  	;xchg	bl, al	 	
  2019                                  	;and	bl, 0Fh
  2020                                  	;mov	ah, [ebx+hexchrs]
  2021                                  	;pop	ebx	
  2022                                  	;retn
  2023                                  
  2024                                  dwordtohex:
  2025                                  	; INPUT ->
  2026                                  	; 	EAX = dword (binary number)
  2027                                  	; OUTPUT ->
  2028                                  	;	EDX:EAX = hexadecimal string
  2029                                  	;
  2030 000016EF 50                      	push	eax
  2031 000016F0 C1E810                  	shr	eax, 16
  2032 000016F3 E8D2FFFFFF              	call	wordtohex
  2033 000016F8 89C2                    	mov	edx, eax
  2034 000016FA 58                      	pop	eax
  2035                                  	;call	wordtohex
  2036                                  	;retn
  2037                                  	; 02/01/2022
  2038 000016FB EBCD                    	jmp	short wordtohex
  2039                                  
  2040                                  ; 10/05/2015
  2041                                  hex_digits:
  2042                                  hexchrs:
  2043 000016FD 303132333435363738-     	db '0123456789ABCDEF'
  2043 00001706 39414243444546     
  2044                                  
  2045                                  ; Convert binary number to decimal/numeric string
  2046                                  ; 06/11/2014
  2047                                  ; Temporary Code
  2048                                  ;
  2049                                  
  2050                                  bintdstr:
  2051                                  	; EAX = binary number
  2052                                  	; ESI = decimal/numeric string address
  2053                                  	; EBX = divisor (10)
  2054                                  	; ECX = string length (<=10)
  2055 0000170D 01CE                    	add	esi, ecx
  2056                                  btdstr0:
  2057 0000170F 4E                      	dec	esi
  2058 00001710 31D2                    	xor	edx, edx
  2059 00001712 F7F3                    	div	ebx
  2060 00001714 80C230                  	add	dl, 30h
  2061 00001717 8816                    	mov	[esi], dl
  2062 00001719 FEC9                    	dec	cl
  2063 0000171B 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2064 0000171D 09C0                    	or	eax, eax
  2065 0000171F 75EE                    	jnz	short btdstr0
  2066                                  btdstr1:
  2067 00001721 4E                      	dec	esi
  2068 00001722 C60620                          mov     byte [esi], 20h ; blank space
  2069 00001725 FEC9                    	dec	cl
  2070 00001727 75F8                    	jnz	short btdstr1
  2071                                  btdstr2:
  2072 00001729 C3                      	ret
  2073                                  
  2074                                  ; Calculate free memory pages on M.A.T.
  2075                                  ; 06/11/2014
  2076                                  ; Temporary Code
  2077                                  ;
  2078                                  
  2079                                  calc_free_mem:
  2080 0000172A 31D2                    	xor	edx, edx
  2081                                  	;xor	ecx, ecx
  2082                                  	;mov	cx, [mat_size] ; in pages
  2083                                  	; 02/01/2022
  2084 0000172C 8B0D[F0640000]          	mov	ecx, [mat_size] ; in pages
  2085 00001732 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2086 00001735 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2087                                  cfm0:
  2088 0000173A AD                      	lodsd
  2089 0000173B 51                      	push	ecx
  2090 0000173C B920000000              	mov	ecx, 32
  2091                                  cfm1:
  2092 00001741 D1E8                    	shr	eax, 1
  2093 00001743 7301                    	jnc	short cfm2
  2094 00001745 42                      	inc	edx
  2095                                  cfm2:
  2096 00001746 E2F9                    	loop	cfm1
  2097 00001748 59                      	pop	ecx
  2098 00001749 E2EF                    	loop	cfm0
  2099 0000174B C3                      	ret
  2100                                  
  2101                                  %include 'diskio.inc'  ; 07/03/2015
  2102                              <1> ; Retro UNIX 386 v1.1 Kernel (v0.2.1.5) - DISKIO.INC
  2103                              <1> ; Last Modification: 10/07/2022
  2104                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2105                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2106                              <1> 
  2107                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2108                              <1> 
  2109                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2110                              <1> 
  2111                              <1> ; 06/02/2015
  2112                              <1> diskette_io:
  2113 0000174C 9C                  <1> 	pushfd
  2114 0000174D 0E                  <1> 	push 	cs
  2115 0000174E E809000000          <1> 	call 	DISKETTE_IO_1
  2116 00001753 C3                  <1> 	retn
  2117                              <1> 	
  2118                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2119                              <1> ;//////////////////////////////////////////////////////
  2120                              <1> 
  2121                              <1> ; 08/07/2022 - (diskio code has been simplified/shortened 
  2122                              <1> ;		by removing unused IBM PC-AT disk functions)
  2123                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2124                              <1> ; 20/02/2015
  2125                              <1> ; 06/02/2015 (unix386.s)
  2126                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2127                              <1> ;
  2128                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2129                              <1> ;
  2130                              <1> ; ADISK.EQU
  2131                              <1> 
  2132                              <1> ;----- Wait control constants 
  2133                              <1> 
  2134                              <1> ;amount of time to wait while RESET is active.
  2135                              <1> 
  2136                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2137                              <1> 					;at 250 KBS xfer rate.
  2138                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2139                              <1> 
  2140                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2141                              <1> 					;status register to become valid
  2142                              <1> 					;before re-reading.
  2143                              <1> 
  2144                              <1> ;After sending a byte to NEC, status register may remain
  2145                              <1> ;incorrectly set for 24 us.
  2146                              <1> 
  2147                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2148                              <1> 					;RQM low.
  2149                              <1> 
  2150                              <1> ; COMMON.MAC
  2151                              <1> ;
  2152                              <1> ;	Timing macros
  2153                              <1> ;
  2154                              <1> 
  2155                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2156                              <1> 		jmp short $+2
  2157                              <1> %endmacro		
  2158                              <1> 
  2159                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2160                              <1> 		jmp short $+2
  2161                              <1> 		jmp short $+2
  2162                              <1> %endmacro
  2163                              <1> 
  2164                              <1> %macro		NEWIODELAY 0
  2165                              <1> 		out	0EBh,al
  2166                              <1> %endmacro 
  2167                              <1> 
  2168                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2169                              <1> ;;; WAIT_FOR_MEM
  2170                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2171                              <1> ;WAIT_FDU_INT_HI	equ	1
  2172                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2173                              <1> ;;; WAIT_FOR_PORT
  2174                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2175                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2176                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2177                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2178                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2179                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2180                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2181                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2182                              <1> ;;; WAIT_REFRESH
  2183                              <1> ;amount of time to wait for head settle, per unit in parameter
  2184                              <1> ;table = 1 ms.
  2185                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2186                              <1> 
  2187                              <1> 
  2188                              <1> ; //////////////// DISKETTE I/O ////////////////
  2189                              <1> 
  2190                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2191                              <1> 
  2192                              <1> ;----------------------------------------
  2193                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2194                              <1> ;----------------------------------------
  2195                              <1> 
  2196                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2197                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2198                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2199                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2200                              <1> 
  2201                              <1> ;----------------------------------------
  2202                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2203                              <1> ;-------------------------------------------------------------------------------
  2204                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2205                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2206                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2207                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2208                              <1> 
  2209                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2210                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2211                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2212                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2213                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2214                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2215                              <1> 
  2216                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2217                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2218                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2219                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2220                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2221                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2222                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2223                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2224                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2225                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2226                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2227                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2228                              <1> 
  2229                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2230                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2231                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2232                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2233                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2234                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2235                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2236                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2237                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2238                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2239                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2240                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2241                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2242                              <1> 
  2243                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2244                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2245                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2246                              <1> 
  2247                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2248                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2249                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2250                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2251                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2252                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2253                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2254                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2255                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2256                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2257                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2258                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2259                              <1> 
  2260                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2261                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2262                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2263                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2264                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2265                              <1> 
  2266                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2267                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2268                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2269                              <1> INTA01		EQU	021H		; 8259 PORT
  2270                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2271                              <1> INTB01		EQU	0A1H		;
  2272                              <1> 
  2273                              <1> ;-------------------------------------------------------------------------------
  2274                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2275                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2276                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2277                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2278                              <1> ;-------------------------------------------------------------------------------
  2279                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2280                              <1> 
  2281                              <1> ;-------------------------------------------------------------------------------
  2282                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2283                              <1> 
  2284                              <1> ; 10/07/222
  2285                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2286                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2287                              <1> ; (unix386.s <-- dsectrm2.s)
  2288                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2289                              <1> 
  2290                              <1> ; 10/12/2014
  2291                              <1> ;
  2292                              <1> ;int40h:
  2293                              <1> ;	pushf
  2294                              <1> ;	push 	cs
  2295                              <1> ;	;cli
  2296                              <1> ;	call 	DISKETTE_IO_1
  2297                              <1> ;	retn
  2298                              <1> 
  2299                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2300                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2301                              <1> ;
  2302                              <1> 
  2303                              <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022-------------------------
  2304                              <1> ; DISKETTE I/O
  2305                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2306                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2307                              <1> ; INPUT
  2308                              <1> ;	(AH)= 00H RESET DISKETTE SYSTEM
  2309                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2310                              <1> ;		ON ALL DRIVES
  2311                              <1> ;------------------------------------------------------------------------------- 
  2312                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY
  2313                              <1> ;-------------------------------------------------------------------------------
  2314                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY
  2315                              <1> ;-------------------------------------------------------------------------------
  2316                              <1> ;
  2317                              <1> ;	REGISTERS FOR READ/WRITE
  2318                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2319                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2320                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2321                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2322                              <1> ;		320/360	320/360	    0-39
  2323                              <1> ;		320/360	1.2M	    0-39
  2324                              <1> ;		1.2M	1.2M	    0-79
  2325                              <1> ;		720K	720K	    0-79
  2326                              <1> ;		1.44M	1.44M	    0-79	
  2327                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED)
  2328                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2329                              <1> ;		320/360	320/360	     1-8/9
  2330                              <1> ;		320/360	1.2M	     1-8/9
  2331                              <1> ;		1.2M	1.2M	     1-15
  2332                              <1> ;		720K	720K	     1-9
  2333                              <1> ;		1.44M	1.44M	     1-18		
  2334                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2335                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2336                              <1> ;		320/360	320/360	        8/9
  2337                              <1> ;		320/360	1.2M	        8/9
  2338                              <1> ;		1.2M	1.2M		15
  2339                              <1> ;		720K	720K		9
  2340                              <1> ;		1.44M	1.44M		18
  2341                              <1> ;
  2342                              <1> ;	(EBX) - ADDRESS OF BUFFER
  2343                              <1> ;
  2344                              <1> ;-------------------------------------------------------------------------------
  2345                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2346                              <1> ;	AH = STATUS OF OPERATION
  2347                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2348                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2349                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)
  2350                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2351                              <1> ;	FOR READ/WRITE/VERIFY
  2352                              <1> ;		DS,BX,DX,CX PRESERVED
  2353                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2354                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2355                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2356                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2357                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2358                              <1> ;-------------------------------------------------------------------------------
  2359                              <1> ;
  2360                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2361                              <1> ;
  2362                              <1> ;   -----------------------------------------------------------------
  2363                              <1> ;   |       |       |       |       |       |       |       |       |
  2364                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2365                              <1> ;   |       |       |       |       |       |       |       |       |
  2366                              <1> ;   -----------------------------------------------------------------
  2367                              <1> ;	|	|	|	|	|	|	|	|
  2368                              <1> ;	|	|	|	|	|	-----------------
  2369                              <1> ;	|	|	|	|	|		|
  2370                              <1> ;	|	|	|	|    RESERVED		|
  2371                              <1> ;	|	|	|	|		  PRESENT STATE
  2372                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2373                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2374                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2375                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2376                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2377                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2378                              <1> ;	|	|	|	|	110: RESERVED
  2379                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2380                              <1> ;	|	|	|	|
  2381                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2382                              <1> ;	|	|	|
  2383                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED
  2384                              <1> ;	|	|					 (360K IN 1.2M DRIVE)
  2385                              <1> ;	|	|
  2386                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2387                              <1> ;
  2388                              <1> ;						00: 500 KBS
  2389                              <1> ;						01: 300 KBS
  2390                              <1> ;						10: 250 KBS
  2391                              <1> ;						11: RESERVED
  2392                              <1> ;
  2393                              <1> ;
  2394                              <1> 
  2395                              <1> struc MD
  2396 00000000 ??                  <1> 	.SPEC1:	  resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2397 00000001 ??                  <1> 	.SPEC2:	  resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2398 00000002 ??                  <1> 	.OFF_TIM: resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2399 00000003 ??                  <1> 	.BYT_SEC: resb	1	; 512 BYTES/SECTOR
  2400 00000004 ??                  <1> 	.SEC_TRK: resb	1	; EOT (LAST SECTOR ON TRACK)
  2401 00000005 ??                  <1> 	.GAP:	  resb	1	; GAP LENGTH
  2402 00000006 ??                  <1> 	.DTL:	  resb	1	; DTL
  2403 00000007 ??                  <1> 	.GAP3:	  resb	1	; GAP LENGTH FOR FORMAT
  2404 00000008 ??                  <1> 	.FIL_BYT: resb	1	; FILL BYTE FOR FORMAT
  2405 00000009 ??                  <1> 	.HD_TIM:  resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2406 0000000A ??                  <1> 	.STR_TIM: resb	1	; MOTOR START TIME (1/8 SECONDS)
  2407 0000000B ??                  <1> 	.MAX_TRK: resb	1	; MAX. TRACK NUMBER
  2408 0000000C ??                  <1> 	.RATE:	  resb	1	; DATA TRANSFER RATE
  2409                              <1> endstruc
  2410                              <1> 
  2411                              <1> BIT7OFF	EQU	7FH
  2412                              <1> BIT7ON	EQU	80H
  2413                              <1> 
  2414                              <1> ;;int13h: ; 16/02/2015
  2415                              <1> ;; 16/02/2015 - 21/02/2015
  2416                              <1> int40h:
  2417 00001754 9C                  <1> 	pushfd
  2418 00001755 0E                  <1> 	push 	cs
  2419 00001756 E801000000          <1> 	call 	DISKETTE_IO_1
  2420 0000175B C3                  <1> 	retn	
  2421                              <1> 
  2422                              <1> DISKETTE_IO_1:
  2423                              <1> 
  2424 0000175C FB                  <1> 	sti				; INTERRUPTS BACK ON
  2425 0000175D 55                  <1> 	push	ebp			; USER REGISTER
  2426 0000175E 57                  <1> 	push	edi			; USER REGISTER
  2427 0000175F 52                  <1> 	push	edx			; HEAD #, DRIVE # OR USER REGISTER
  2428 00001760 53                  <1> 	push	ebx			; BUFFER OFFSET PARAMETER OR REGISTER
  2429 00001761 51                  <1> 	push	ecx			; TRACK #-SECTOR # OR USER REGISTER
  2430 00001762 89E5                <1> 	mov	ebp, esp		; EBP     => PARAMETER LIST DEP. ON AH
  2431                              <1> 					; [EBP]   = SECTOR #
  2432                              <1> 					; [EBP+1] = TRACK #
  2433                              <1> 					; [EBP+4] = BUFFER OFFSET
  2434                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2435                              <1> 					; CL/[EBP] = BITS 7&6 HI BITS OF MAX CYL
  2436                              <1> 					; 	     BITS 0-5 MAX SECTORS/TRACK
  2437                              <1> 					; CH/[EBP+1] = LOW 8 BITS OF MAX CYL.
  2438                              <1> 					; BL/[EBP+4] = BITS 7-4 = 0
  2439                              <1> 					;	       BITS 3-0 = VALID CMOS TYPE
  2440                              <1> 					; BH/[EBP+5] = 0
  2441                              <1> 					; DL/[EBP+8] = # DRIVES INSTALLED
  2442                              <1> 					; DH/[EBP+9] = MAX HEAD #
  2443                              <1> 					; EDI/[EBP+12] = OFFSET TO DISK BASE
  2444                              <1> 
  2445 00001764 56                  <1> 	push	esi			; USER REGISTER
  2446                              <1> 
  2447                              <1> 	; 10/07/2022
  2448                              <1> 	;or	ah, ah			; RESET ?
  2449                              <1> 	;jnz	short diskette_io_2	; NO
  2450                              <1> 
  2451                              <1> 	;jmp	DSK_RESET
  2452                              <1> 
  2453                              <1> diskette_io_2:
  2454 00001765 80FC02              <1> 	cmp	ah, 2			; READ OR WRITE ?
  2455 00001768 7605                <1> 	jna	short diskette_io_3	; YES
  2456 0000176A E9DC010000          <1> 	jmp	FNC_ERR			; INVALID FUNCTION
  2457                              <1> diskette_io_3:
  2458 0000176F 80FA01              <1> 	cmp	dl, 1			; DRIVES 0 AND 1 OK
  2459 00001772 7605                <1> 	jna	short diskette_io_4
  2460 00001774 E9D2010000          <1> 	jmp	FNC_ERR			; INVALID FUNCTION
  2461                              <1> diskette_io_4:
  2462                              <1> OK_DRV:
  2463                              <1> 	; 08/07/2022
  2464 00001779 31C9                <1> 	xor	ecx, ecx
  2465 0000177B 88E1                <1> 	mov	cl, ah			; ECX = FUNCTION
  2466 0000177D 0FB6FA              <1> 	movzx	edi, dl ; drive number	; DI = DRIVE #
  2467                              <1> 	; 11/12/2014
  2468 00001780 8815[C15F0000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')
  2469 00001786 88C2                <1> 	mov	dl, al	; # of sectors
  2470 00001788 0FB7F2              <1> 	movzx	esi, dx ;		; SI = HEAD #,# OF SECTORS
  2471 0000178B C0E102              <1> 	shl	cl, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2472 0000178E BB[AE170000]        <1> 	mov	ebx, FNC_TAB		; LOAD START OF FUNCTION TABLE
  2473 00001793 01CB                <1> 	add	ebx, ecx		; ADD OFFSET INTO TABLE => ROUTINE
  2474                              <1> 	;
  2475                              <1> 	;mov	ah, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2476 00001795 C605[5C650000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; INITIALIZE FOR ALL OTHERS
  2477                              <1> 
  2478                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2479                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2480                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2481                              <1> ;
  2482                              <1> ;		EDI	: DRIVE #
  2483                              <1> ;		SI-HI	: HEAD #
  2484                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2485                              <1> ;		[EBP]	: SECTOR #
  2486                              <1> ;		[EBP+1]	: TRACK #
  2487                              <1> ;		[EBP+4]	: BUFFER OFFSET
  2488                              <1> ;
  2489                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2490                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2491                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2492                              <1> ;	SPECIFIC ERROR CODE.
  2493                              <1> ;
  2494                              <1> 					; (AH) = @DSKETTE_STATUS
  2495 0000179C FF13                <1> 	call	dword [ebx]		; CALL THE REQUESTED FUNCTION
  2496                              <1> 	; 08/07/2022
  2497 0000179E 5E                  <1> 	pop	esi			; RESTORE ALL REGISTERS
  2498 0000179F 59                  <1> 	pop	ecx
  2499 000017A0 5B                  <1> 	pop	ebx
  2500 000017A1 5A                  <1> 	pop	edx
  2501 000017A2 5F                  <1> 	pop	edi
  2502 000017A3 89E5                <1> 	mov	ebp, esp
  2503 000017A5 50                  <1> 	push	eax
  2504 000017A6 9C                  <1> 	pushfd
  2505 000017A7 58                  <1> 	pop	eax
  2506 000017A8 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015 - flags
  2507 000017AB 58                  <1> 	pop	eax
  2508 000017AC 5D                  <1> 	pop	ebp
  2509 000017AD CF                  <1> 	iretd
  2510                              <1> 
  2511                              <1> ;-------------------------------------------------------------------------------
  2512                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (kernel v0.2.1.5)
  2513                              <1> 
  2514                              <1> FNC_TAB:
  2515 000017AE [D6180000]          <1> 	dd	DSK_RESET		; AH = 00H; RESET
  2516 000017B2 [BA170000]          <1> 	dd	DSK_READ		; AH = 01H; READ
  2517 000017B6 [C7170000]          <1> 	dd	DSK_WRITE		; AH = 02H; WRITE
  2518                              <1> FNC_TAE EQU     $			; END
  2519                              <1> 
  2520                              <1> ;-------------------------------------------------------------------------------
  2521                              <1> ; DISK_READ	(AH = 01H)  ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2522                              <1> ;	DISKETTE READ.
  2523                              <1> ;
  2524                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2525                              <1> ;		SI-HI	: HEAD #
  2526                              <1> ;		SI-LOW	: # OF SECTORS
  2527                              <1> ;		ES	: BUFFER SEGMENT
  2528                              <1> ;		[BP]	: SECTOR #
  2529                              <1> ;		[BP+1]	: TRACK #
  2530                              <1> ;		[BP+2]	: BUFFER OFFSET
  2531                              <1> ;
  2532                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2533                              <1> ;-------------------------------------------------------------------------------
  2534                              <1> 
  2535                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2536                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2537                              <1> 
  2538                              <1> DSK_READ:
  2539 000017BA 8025[5A650000]7F    <1> 	and	byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION
  2540 000017C1 66B846E6            <1> 	mov	ax, 0E646h		; AX = NEC COMMAND, DMA COMMAND
  2541                              <1> 	;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2542                              <1> 	;retn
  2543 000017C5 EB0B                <1> 	jmp	short RD_WR_VF
  2544                              <1> 
  2545                              <1> ;-------------------------------------------------------------------------------
  2546                              <1> ; DISK_WRITE	(AH = 02H)
  2547                              <1> ;	DISKETTE WRITE.
  2548                              <1> ;
  2549                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2550                              <1> ;		SI-HI	: HEAD #
  2551                              <1> ;		SI-LOW	: # OF SECTORS
  2552                              <1> ;		ES	: BUFFER SEGMENT
  2553                              <1> ;		[BP]	: SECTOR #
  2554                              <1> ;		[BP+1]	: TRACK #
  2555                              <1> ;		[BP+2]	: BUFFER OFFSET
  2556                              <1> ;
  2557                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2558                              <1> ;-------------------------------------------------------------------------------
  2559                              <1> 
  2560                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2561                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2562                              <1> 
  2563                              <1> DSK_WRITE:
  2564 000017C7 66B84AC5            <1> 	mov	ax, 0C54Ah		; AX = NEC COMMAND, DMA COMMAND
  2565 000017CB 800D[5A650000]80    <1>         or	byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION
  2566                              <1> 	;;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2567                              <1> 	;;retn
  2568                              <1> 	;jmp	short RD_WR_VF
  2569                              <1> 
  2570                              <1> ;-------------------------------------------------------------------------------
  2571                              <1> ; RD_WR_VF
  2572                              <1> ;	COMMON READ, WRITE
  2573                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  2574                              <1> ;
  2575                              <1> ; ON ENTRY:	AH = READ/WRITE NEC PARAMETER
  2576                              <1> ;		AL = READ/WRITE DMA PARAMETER
  2577                              <1> ;
  2578                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2579                              <1> ;-------------------------------------------------------------------------------
  2580                              <1> 
  2581                              <1> RD_WR_VF:
  2582                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2583 000017D2 50                  <1> 	push	eax ; 24/12/2021	; SAVE DMA, NEC PARAMETERS
  2584 000017D3 E8EA010000          <1> 	call	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2585 000017D8 E851020000          <1> 	call	SETUP_STATE		; INITIALIZE START AND END RATE
  2586 000017DD 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2587                              <1> DO_AGAIN:
  2588 000017DE 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE PARAMETER
  2589 000017DF E88B020000          <1> 	call	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  2590 000017E4 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2591                              <1> 	; 24/12/2021
  2592 000017E5 7305                <1> 	jnc	short RWV
  2593 000017E7 E9C0000000          <1> 	jmp	RWV_END			; MEDIA CHANGE ERROR OR TIME-OUT
  2594                              <1> RWV:
  2595 000017EC 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE/VERIFY PARAMETER
  2596 000017ED 8AB7[67650000]      <1> 	mov	dh, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  2597 000017F3 80E6C0              <1> 	and	dh, RATE_MSK		; KEEP ONLY RATE
  2598 000017F6 E89F050000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  2599                              <1> 	; 20/02/2015
  2600 000017FB 744D                <1> 	jz	short RWV_ASSUME	; ERROR IN CMOS
  2601 000017FD 3C01                <1> 	cmp	al, 1			; 40 TRACK DRIVE?
  2602 000017FF 750D                <1> 	jne	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  2603 00001801 F687[67650000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  2604 00001808 7413                <1> 	jz	short RWV_2		; YES, CMOS IS CORRECT
  2605 0000180A B002                <1> 	mov	al, 2			; CHANGE TO 1.2M
  2606 0000180C EB0F                <1> 	jmp	short RWV_2
  2607                              <1> RWV_1:
  2608 0000180E 720D                <1> 	jb	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  2609 00001810 F687[67650000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK?
  2610 00001817 7504                <1> 	jnz	short RWV_2		; NO, 80 TRACK
  2611 00001819 B001                <1> 	mov	al, 1			; IT IS 40 TRACK, FIX CMOS VALUE
  2612 0000181B EB04                <1> 	jmp	short RWV_3
  2613                              <1> RWV_2:
  2614 0000181D 08C0                <1> 	or	al, al			; TEST FOR NO DRIVE
  2615 0000181F 7429                <1> 	jz	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  2616                              <1> RWV_3:
  2617 00001821 E831010000          <1> 	call	DR_TYPE_CHECK		; RTN EBX = MEDIA/DRIVE PARAM TBL.
  2618 00001826 7222                <1> 	jc	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  2619                              <1> 
  2620                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  2621                              <1> 
  2622 00001828 57                  <1> 	push	edi			; SAVE DRIVE #
  2623                              <1> 	;xor	ebx, ebx		; EBX = INDEX TO DR_TYPE TABLE
  2624 00001829 BB[4C5F0000]        <1> 	mov	ebx, DR_TYPE
  2625                              <1> 	;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2626 0000182E B106                <1> 	mov	cl, DR_CNT
  2627                              <1> RWV_DR_SEARCH:
  2628                              <1> 	;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2629 00001830 8A23                <1> 	mov	ah, [ebx]
  2630 00001832 80E47F              <1> 	and	ah, BIT7OFF		; MASK OUT MSB
  2631 00001835 38E0                <1> 	cmp	al, ah			; DRIVE TYPE MATCH?
  2632 00001837 7509                <1> 	jne	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  2633                              <1> RWV_DR_FND:
  2634                              <1> 	;mov	edi, [DR_TYPE+ebx+1] 	; EDI = MEDIA/DRIVE PARAMETER TABLE
  2635 00001839 43                  <1> 	inc	ebx
  2636 0000183A 8B3B                <1> 	mov	edi, [ebx]
  2637 0000183C 4B                  <1> 	dec	ebx
  2638                              <1> RWV_MD_SEARH:
  2639 0000183D 3A770C              <1>         cmp	dh, [edi+MD.RATE]       ; MATCH?
  2640 00001840 741D                <1> 	je	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  2641                              <1> RWV_NXT_MD:
  2642 00001842 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2643                              <1> 	;loop	RWV_DR_SEARCH
  2644 00001845 FEC9                <1> 	dec	cl
  2645 00001847 75E7                <1> 	jnz	short RWV_DR_SEARCH 
  2646 00001849 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2647                              <1> 
  2648                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  2649                              <1> 
  2650                              <1> RWV_ASSUME:
  2651 0000184A BB[6A5F0000]        <1> 	mov	ebx, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  2652 0000184F F687[67650000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK
  2653 00001856 740A                <1> 	jz	short RWV_MD_FND1	; MUST BE 40 TRACK
  2654 00001858 BB[845F0000]        <1> 	mov	ebx, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  2655 0000185D EB03                <1> 	jmp	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  2656                              <1> 
  2657                              <1> ;-----	EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  2658                              <1> 	 			
  2659                              <1> RWV_MD_FND:
  2660 0000185F 89FB                <1> 	mov	ebx, edi		; EBX = MEDIA/DRIVE PARAMETER TABLE
  2661 00001861 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2662                              <1> 	
  2663                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  2664                              <1> 
  2665                              <1> RWV_MD_FND1:
  2666 00001862 E83B010000          <1> 	call	SEND_SPEC_MD
  2667 00001867 E871020000          <1> 	call	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  2668 0000186C 7405                <1> 	jz	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  2669 0000186E E84A020000          <1> 	call	SEND_RATE		; SEND DATA RATE TO NEC
  2670                              <1> RWV_DBL:
  2671 00001873 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2672 00001874 E87F040000          <1> 	call	SETUP_DBL		; CHECK FOR DOUBLE STEP
  2673 00001879 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2674 0000187A 7223                <1> 	jc	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  2675                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2676                              <1> 	;push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2677                              <1> 	; 08/07/2022
  2678 0000187C 8B0424              <1> 	mov	eax, [esp]
  2679 0000187F 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2680 00001880 E86D020000          <1> 	call	DMA_SETUP		; SET UP THE DMA
  2681 00001885 5B                  <1> 	pop	ebx
  2682 00001886 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2683 00001887 722D                <1> 	jc	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  2684 00001889 50                  <1> 	push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2685 0000188A 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2686 0000188B E8C5020000          <1> 	call	NEC_INIT		; INITIALIZE NEC
  2687 00001890 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2688 00001891 720C                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2689 00001893 E8EC020000          <1> 	call	RWV_COM			; OP CODE COMMON TO READ/WRITE
  2690 00001898 7205                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2691 0000189A E830030000          <1> 	call	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  2692                              <1> CHK_RET:
  2693 0000189F E8CF030000          <1> 	call	RETRY			; CHECK FOR, SETUP RETRY
  2694 000018A4 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2695 000018A5 7305                <1> 	jnc	short RWV_END		; CY = 0 NO RETRY
  2696 000018A7 E932FFFFFF          <1>         jmp	DO_AGAIN                ; CY = 1 MEANS RETRY
  2697                              <1> RWV_END:
  2698 000018AC E87A030000          <1> 	call	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  2699 000018B1 E80B040000          <1> 	call	NUM_TRANS		; AL = NUMBER TRANSFERRED
  2700                              <1> RWV_BAC:
  2701                              <1> 	; 08/07/2022			; BAD DMA ERROR ENTRY
  2702                              <1> 	;push	eax ; 24/12/2021	; SAVE NUMBER TRANSFERRED
  2703                              <1> 	;CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2704                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NUMBER TRANSFERRED
  2705                              <1> 	;;call	SETUP_END		; VARIOUS CLEANUPS
  2706                              <1> 	;;retn
  2707                              <1> 	;jmp	SETUP_END
  2708                              <1> 
  2709                              <1> ;-------------------------------------------------------------------------------
  2710                              <1> ; SETUP_END
  2711                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  2712                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  2713                              <1> ;
  2714                              <1> ; ON EXIT:
  2715                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2716                              <1> ;-------------------------------------------------------------------------------
  2717                              <1> SETUP_END:
  2718                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 
  2719                              <1> 	;mov	dl, 2			; GET THE MOTOR WAIT PARAMETER
  2720                              <1> 	;push	ax			; SAVE NUMBER TRANSFERRED
  2721 000018B6 50                  <1> 	push	eax ; 24/12/2021
  2722 000018B7 B002                <1> 	mov	al, 2 ; 08/07/2022
  2723 000018B9 E8E5040000          <1> 	call	GET_PARM
  2724 000018BE 8825[5B650000]      <1> 	mov	[MOTOR_COUNT], ah	; STORE UPON RETURN
  2725                              <1> 	;pop	ax			; RESTORE NUMBER TRANSFERRED
  2726 000018C4 58                  <1> 	pop	eax ; 24/12/2021
  2727 000018C5 8A25[5C650000]      <1> 	mov	ah, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  2728 000018CB 08E4                <1> 	or	ah, ah			; CHECK FOR ERROR
  2729 000018CD 7406                <1> 	jz	short NUN_ERR		; NO ERROR
  2730 000018CF 30C0                <1> 	xor 	al, al			; CLEAR NUMBER RETURNED
  2731                              <1> ;NUN_ERR: 
  2732 000018D1 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  2733 000018D4 F5                  <1> 	cmc				; SUCCESS OR FAILURE
  2734                              <1> NUN_ERR:
  2735 000018D5 C3                  <1> 	retn
  2736                              <1> 
  2737                              <1> ;-------------------------------------------------------------------------------
  2738                              <1> ; DISK_RESET	(AH = 00H)	
  2739                              <1> ;		RESET THE DISKETTE SYSTEM.
  2740                              <1> ;
  2741                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2742                              <1> ;-------------------------------------------------------------------------------
  2743                              <1> DSK_RESET:
  2744                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2745 000018D6 66BAF203            <1> 	mov	dx, 03F2h		; ADAPTER CONTROL PORT
  2746 000018DA FA                  <1> 	cli				; NO INTERRUPTS
  2747 000018DB A0[5A650000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2748 000018E0 243F                <1> 	and	al, 00111111b		; KEEP SELECTED AND MOTOR ON BITS
  2749 000018E2 C0C004              <1> 	rol	al, 4			; MOTOR VALUE TO HIGH NIBBLE
  2750                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2751 000018E5 0C08                <1> 	or	al, 00001000b		; TURN ON INTERRUPT ENABLE
  2752 000018E7 EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2753 000018E8 C605[59650000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2754                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2755                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2756                              <1> 					;      PULSE WIDTH)
  2757                              <1> 	; 19/12/2014
  2758                              <1> 	NEWIODELAY
  2165 000018EF E6EB                <2>  out 0EBh,al
  2759                              <1> 
  2760                              <1> 	; 17/12/2014 
  2761                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2762 000018F1 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2763                              <1> wdw1:
  2764                              <1> 	NEWIODELAY   ; 27/02/2015
  2165 000018F6 E6EB                <2>  out 0EBh,al
  2765 000018F8 E2FC                <1> 	loop	wdw1
  2766                              <1> 	;
  2767 000018FA 0C04                <1> 	or	al, 00000100b		; TURN OFF RESET BIT
  2768 000018FC EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2769                              <1> 	; 16/12/2014
  2770                              <1> 	IODELAY
  2160 000018FD EB00                <2>  jmp short $+2
  2161 000018FF EB00                <2>  jmp short $+2
  2771                              <1> 	;
  2772                              <1> 	;sti				; ENABLE THE INTERRUPTS
  2773 00001901 E8A2060000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  2774 00001906 723A                <1> 	jc	short DR_ERR		; IF ERROR, RETURN IT
  2775 00001908 66B9C000            <1> 	mov	cx, 11000000b		; CL = EXPECTED @NEC_STATUS
  2776                              <1> NXT_DRV:
  2777                              <1> 	; 24/12/2021
  2778 0000190C 51                  <1> 	push	ecx			; SAVE FOR CALL
  2779 0000190D B8[41190000]        <1> 	mov	eax, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2780 00001912 50                  <1> 	push	eax			;
  2781 00001913 B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  2782 00001915 E884050000          <1> 	call	NEC_OUTPUT
  2783 0000191A 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  2784 0000191B E8B8060000          <1> 	call	RESULTS			; READ IN THE RESULTS
  2785                              <1> 	; 24/12/2021
  2786 00001920 59                  <1> 	pop	ecx			; RESTORE AFTER CALL
  2787 00001921 721F                <1> 	jc	short DR_ERR		; ERROR RETURN
  2788 00001923 3A0D[5D650000]      <1> 	cmp	cl, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2789 00001929 7517                <1> 	jnz	short DR_ERR		; EVERYTHING OK
  2790 0000192B FEC1                <1> 	inc	cl			; NEXT EXPECTED @NEC_STATUS
  2791 0000192D 80F9C3              <1> 	cmp	cl, 11000011b		; ALL POSSIBLE DRIVES CLEARED
  2792 00001930 76DA                <1> 	jbe	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2793                              <1> 	;
  2794 00001932 E842000000          <1> 	call	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2795                              <1> RESBAC:
  2796 00001937 E87AFFFFFF          <1> 	call	SETUP_END		; VARIOUS CLEANUPS
  2797                              <1> 	; 24/12/2021
  2798 0000193C 89F3                <1> 	mov	ebx, esi		; GET SAVED AL TO BL
  2799 0000193E 88D8                <1> 	mov	al, bl			; PUT BACK FOR RETURN
  2800 00001940 C3                  <1> 	retn		
  2801                              <1> DR_POP_ERR:
  2802                              <1> 	; 24/12/2021
  2803 00001941 59                  <1> 	pop	ecx			; CLEAR STACK
  2804                              <1> DR_ERR:
  2805 00001942 800D[5C650000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE
  2806 00001949 EBEC                <1> 	jmp	short RESBAC		; RETURN FROM RESET
  2807                              <1> 
  2808                              <1> ;-------------------------------------------------------------------------------
  2809                              <1> ; FNC_ERR
  2810                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2811                              <1> ;	SET BAD COMMAND IN STATUS.
  2812                              <1> ;
  2813                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2814                              <1> ;-------------------------------------------------------------------------------
  2815                              <1> 
  2816                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2817                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2818                              <1> 	; 24/12/2021
  2819 0000194B 89F0                <1> 	mov	eax, esi		; RESTORE AL
  2820 0000194D B401                <1> 	mov	ah, BAD_CMD		; SET BAD COMMAND ERROR
  2821 0000194F 8825[5C650000]      <1> 	mov	[DSKETTE_STATUS], ah	; STORE IN DATA AREA
  2822 00001955 F9                  <1> 	stc				; SET CARRY INDICATING ERROR
  2823 00001956 C3                  <1> 	retn
  2824                              <1> 
  2825                              <1> ;----------------------------------------------------------------
  2826                              <1> ; DR_TYPE_CHECK							:
  2827                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  2828                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  2829                              <1> ; ON ENTRY:							:
  2830                              <1> ;	AL = DRIVE TYPE						:
  2831                              <1> ; ON EXIT:							:
  2832                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  2833                              <1> ;	     EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE	:
  2834                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  2835                              <1> ; REGISTERS ALTERED: EBX, ECX ; 08/07/2022 			:
  2836                              <1> ;----------------------------------------------------------------		
  2837                              <1> DR_TYPE_CHECK:
  2838                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)			
  2839                              <1> 	; 24/12/2021
  2840 00001957 50                  <1> 	push	eax
  2841                              <1> 	;push	ecx ; 08/07/2022
  2842                              <1> 	;xor	ebx,ebx			; EBX = INDEX TO DR_TYPE TABLE
  2843 00001958 BB[4C5F0000]        <1> 	mov	ebx, DR_TYPE
  2844                              <1> 	;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2845 0000195D B106                <1> 	mov	cl, DR_CNT
  2846                              <1> TYPE_CHK:	
  2847                              <1> 	;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2848 0000195F 8A23                <1> 	mov	ah, [ebx]
  2849 00001961 38E0                <1> 	cmp	al, ah			; DRIVE TYPE MATCH?
  2850 00001963 740F                <1> 	je	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  2851                              <1> 	; 16/02/2015 (32 bit address modification)
  2852 00001965 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2853                              <1> 	;loop	TYPE_CHK
  2854 00001968 FEC9                <1> 	dec	cl
  2855 0000196A 75F3                <1> 	jnz	short TYPE_CHK
  2856                              <1> 	;
  2857 0000196C BB[AB5F0000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  2858                              <1> 					; Default for GET_PARM (11/12/2014)
  2859                              <1> 	;
  2860 00001971 F9                  <1> 	stc				; DRIVE TYPE NOT FOUND IN TABLE
  2861 00001972 EB03                <1> 	jmp	short TYPE_RTN
  2862                              <1> DR_TYPE_VALID:
  2863                              <1> 	;mov	ebx, [DR_TYPE+ebx+1] 	; EBX = MEDIA TABLE
  2864 00001974 43                  <1> 	inc	ebx
  2865 00001975 8B1B                <1> 	mov	ebx, [ebx]
  2866                              <1> TYPE_RTN:
  2867                              <1> 	;pop	ecx ; 08/07/2022
  2868                              <1> 	; 24/12/2021
  2869 00001977 58                  <1> 	pop	eax
  2870 00001978 C3                  <1> 	retn
  2871                              <1> 		
  2872                              <1> ;----------------------------------------------------------------
  2873                              <1> ; SEND_SPEC							:
  2874                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2875                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  2876                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  2877                              <1> ; ON EXIT:	NONE						:	
  2878                              <1> ; REGISTERS ALTERED: ECX, EDX					:
  2879                              <1> ;----------------------------------------------------------------		
  2880                              <1> SEND_SPEC:
  2881                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2882 00001979 50                  <1> 	push	eax			; SAVE EAX
  2883 0000197A B8[A0190000]        <1> 	mov	eax, SPECBAC		; LOAD ERROR ADDRESS
  2884 0000197F 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2885 00001980 B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2886 00001982 E817050000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2887                              <1> 	;sub	dl, dl			; FIRST SPECIFY BYTE
  2888 00001987 28C0                <1> 	sub	al, al ; 08/07/2022
  2889 00001989 E815040000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2890 0000198E E80B050000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2891                              <1> 	;mov	dl, 1			; SECOND SPECIFY BYTE
  2892 00001993 B001                <1> 	mov	al, 1 ; 08/07/2022
  2893 00001995 E809040000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2894 0000199A E8FF040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2895 0000199F 58                  <1> 	pop	eax			; POP ERROR RETURN
  2896                              <1> SPECBAC:
  2897 000019A0 58                  <1> 	pop	eax			; RESTORE ORIGINAL EAX VALUE
  2898 000019A1 C3                  <1> 	RETn
  2899                              <1> 
  2900                              <1> ;----------------------------------------------------------------
  2901                              <1> ; SEND_SPEC_MD							:
  2902                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2903                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (EBX)	:
  2904                              <1> ; ON ENTRY:	EBX = MEDIA/DRIVE PARAMETER TABLE		:
  2905                              <1> ; ON EXIT:	NONE						:	
  2906                              <1> ; REGISTERS ALTERED: EAX					:
  2907                              <1> ;----------------------------------------------------------------		
  2908                              <1> SEND_SPEC_MD:
  2909                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2910 000019A2 50                  <1> 	push	eax			; SAVE RATE DATA
  2911 000019A3 B8[C0190000]        <1> 	mov	eax, SPEC_ESBAC		; LOAD ERROR ADDRESS
  2912 000019A8 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2913 000019A9 B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2914 000019AB E8EE040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2915 000019B0 8A23                <1>         mov	ah, [ebx+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  2916 000019B2 E8E7040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2917 000019B7 8A6301              <1>         mov	ah, [ebx+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  2918 000019BA E8DF040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2919 000019BF 58                  <1> 	pop	eax			; POP ERROR RETURN
  2920                              <1> SPEC_ESBAC:
  2921 000019C0 58                  <1> 	pop	eax			; RESTORE ORIGINAL EAX VALUE
  2922 000019C1 C3                  <1> 	RETn
  2923                              <1> 
  2924                              <1> ;-------------------------------------------------------------------------------
  2925                              <1> ; XLAT_NEW  
  2926                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  2927                              <1> ;	MODE TO NEW ARCHITECTURE.
  2928                              <1> ;
  2929                              <1> ; ON ENTRY:	EDI = DRIVE #
  2930                              <1> ;-------------------------------------------------------------------------------
  2931                              <1> XLAT_NEW:
  2932                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2933 000019C2 83FF01              <1> 	cmp	edi, 1				; VALID DRIVE
  2934 000019C5 7709                <1> 	ja	short XN_OUT			; IF INVALID BACK
  2935 000019C7 80BF[67650000]00    <1> 	cmp	byte [DSK_STATE+edi], 0		; NO DRIVE ?
  2936 000019CE 7401                <1> 	jz	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  2937                              <1> 	;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2938                              <1> 	;mov	ecx, edi			; ECX = DRIVE NUMBER
  2939                              <1> 	;or	cl, cl
  2940                              <1> 	;jz	short XN_0  ; 08/07/2022
  2941                              <1> 	;shl	cl, 2				; CL = SHIFT COUNT, A=0, B=4
  2942                              <1> 	;;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  2943                              <1> 	;ror	al, cl				; TO LOW NIBBLE
  2944                              <1> ;XN_0:	
  2945                              <1> 	;and	al, DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  2946                              <1>         ;and	byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  2947                              <1> 	;or	[DSK_STATE+edi], al		; UPDATE DRIVE STATE
  2948                              <1> XN_OUT:
  2949 000019D0 C3                  <1> 	retn
  2950                              <1> DO_DET:
  2951                              <1> 	;;call	DRIVE_DET			; TRY TO DETERMINE
  2952                              <1> 	;;retn
  2953                              <1> 	;jmp	DRIVE_DET
  2954                              <1> 
  2955                              <1> ;-------------------------------------------------------------------------------
  2956                              <1> ; DRIVE_DET
  2957                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  2958                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  2959                              <1> ; ON ENTRY:	EDI = DRIVE #
  2960                              <1> ;-------------------------------------------------------------------------------
  2961                              <1> DRIVE_DET:
  2962                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2963 000019D1 E80D040000          <1> 	call	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  2964 000019D6 E87B050000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  2965 000019DB 724E                <1> 	jc	short DD_BAC		; ASSUME NO DRIVE PRESENT
  2966 000019DD B530                <1> 	mov	ch, TRK_SLAP		; SEEK TO TRACK 48
  2967 000019DF E8F3040000          <1> 	call	SEEK
  2968 000019E4 7245                <1> 	jc	short DD_BAC		; ERROR NO DRIVE
  2969 000019E6 B50B                <1> 	mov	ch, QUIET_SEEK+1	; SEEK TO TRACK 10
  2970                              <1> SK_GIN:
  2971 000019E8 FECD                <1> 	dec	ch			; DECREMENT TO NEXT TRACK
  2972                              <1> 	;push	cx		
  2973                              <1> 	; 24/12/2021
  2974 000019EA 51                  <1> 	push	ecx			; SAVE TRACK
  2975 000019EB E8E7040000          <1> 	call	SEEK
  2976 000019F0 723A                <1> 	jc	short POP_BAC		; POP AND RETURN
  2977 000019F2 B8[2C1A0000]        <1> 	mov	eax, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  2978 000019F7 50                  <1> 	push	eax
  2979 000019F8 B404                <1> 	mov	ah, SENSE_DRV_ST	; SENSE DRIVE STATUS COMMAND BYTE
  2980 000019FA E89F040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  2981                              <1> 	; 08/07/2022
  2982 000019FF 89F8                <1> 	mov	eax, edi		; AL = DRIVE
  2983 00001A01 88C4                <1> 	mov	ah, al			; AH = DRIVE
  2984 00001A03 E896040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  2985 00001A08 E8CB050000          <1> 	call	RESULTS			; GO GET STATUS
  2986 00001A0D 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  2987                              <1> 	;pop	cx			; RESTORE TRACK
  2988                              <1> 	; 24/12/2021
  2989 00001A0E 59                  <1> 	pop	ecx
  2990 00001A0F F605[5D650000]10    <1> 	test	byte [NEC_STATUS], HOME	; TRACK 0 ?
  2991 00001A16 74D0                <1> 	jz	short SK_GIN		; GO TILL TRACK 0
  2992 00001A18 08ED                <1> 	or	ch, ch			; IS HOME AT TRACK 0
  2993 00001A1A 7408                <1> 	jz	short IS_80		; MUST BE 80 TRACK DRIVE
  2994                              <1> 
  2995                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  2996                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  2997                              <1> 
  2998 00001A1C 808F[67650000]94    <1> 	or	byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250
  2999 00001A23 C3                  <1> 	retn				; ALL INFORMATION SET
  3000                              <1> IS_80:
  3001 00001A24 808F[67650000]01    <1> 	or	byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  3002                              <1> DD_BAC:
  3003 00001A2B C3                  <1> 	retn
  3004                              <1> POP_BAC:
  3005                              <1> 	;pop	cx			; THROW AWAY
  3006                              <1> 	; 24/12/2021
  3007 00001A2C 59                  <1> 	pop	ecx
  3008 00001A2D C3                  <1> 	retn
  3009                              <1> 
  3010                              <1> ;-------------------------------------------------------------------------------
  3011                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3012                              <1> ;-------------------------------------------------------------------------------
  3013                              <1> SETUP_STATE:
  3014                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3015 00001A2E F687[67650000]10    <1> 	test	byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ?
  3016 00001A35 7537                <1> 	jnz	short J1C		; NO STATES IF DETERMINED
  3017 00001A37 66B84000            <1>        	mov	ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE
  3018 00001A3B F687[67650000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE ?
  3019 00001A42 740D                <1> 	jz	short AX_SET		; DO NOT KNOW DRIVE
  3020 00001A44 F687[67650000]02    <1> 	test	byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE?
  3021 00001A4B 7504                <1> 	jnz	short AX_SET		; JUMP IF YES
  3022 00001A4D 66B88080            <1>         mov	ax, RATE_250*257	; START A END RATE 250 FOR 360 DRIVE
  3023                              <1> AX_SET:	
  3024 00001A51 80A7[67650000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3025 00001A58 08A7[67650000]      <1> 	or	[DSK_STATE+edi], ah	; RATE FIRST TO TRY
  3026 00001A5E 8025[64650000]F3    <1> 	and	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3027 00001A65 C0C804              <1> 	ror	al, 4			; TO OPERATION LAST RATE LOCATION
  3028 00001A68 0805[64650000]      <1> 	or	[LASTRATE], al		; LAST RATE
  3029                              <1> J1C:	
  3030 00001A6E C3                  <1> 	retn
  3031                              <1> 
  3032                              <1> ;-------------------------------------------------------------------------------
  3033                              <1> ; MED_CHANGE	
  3034                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3035                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3036                              <1> ;
  3037                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3038                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3039                              <1> ;-------------------------------------------------------------------------------
  3040                              <1> MED_CHANGE:
  3041                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3042 00001A6F E8BF050000          <1> 	call	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3043 00001A74 7446                <1> 	jz	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3044 00001A76 80A7[67650000]EF    <1> 	and	byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3045                              <1> 
  3046                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3047                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3048                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3049                              <1> 
  3050 00001A7D 89F9                <1> 	mov	ecx, edi		; CL = DRIVE 0
  3051 00001A7F B001                <1> 	mov	al, 1			; MOTOR ON BIT MASK
  3052 00001A81 D2E0                <1> 	shl	al, cl			; TO APPROPRIATE POSITION
  3053 00001A83 F6D0                <1> 	not	al			; KEEP ALL BUT MOTOR ON
  3054 00001A85 FA                  <1> 	cli				; NO INTERRUPTS
  3055 00001A86 2005[5A650000]      <1> 	and	[MOTOR_STATUS], al	; TURN MOTOR OFF INDICATOR
  3056 00001A8C FB                  <1> 	sti				; INTERRUPTS ENABLED
  3057 00001A8D E851030000          <1> 	call	MOTOR_ON		; TURN MOTOR ON
  3058                              <1> 
  3059                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3060                              <1> 
  3061 00001A92 E83FFEFFFF          <1> 	call	DSK_RESET		; RESET NEC
  3062 00001A97 B501                <1> 	mov	ch, 1			; MOVE TO CYLINDER 1
  3063 00001A99 E839040000          <1> 	call	SEEK			; ISSUE SEEK
  3064 00001A9E 30ED                <1> 	xor	ch, ch			; MOVE TO CYLINDER 0
  3065 00001AA0 E832040000          <1> 	call	SEEK			; ISSUE SEEK
  3066 00001AA5 C605[5C650000]06    <1> 	mov	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3067                              <1> OK1:
  3068 00001AAC E882050000          <1> 	call	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3069 00001AB1 7407                <1> 	jz	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3070                              <1> OK4:
  3071 00001AB3 C605[5C650000]80    <1> 	mov	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3072                              <1> OK2:		
  3073 00001ABA F9                  <1> 	stc				; MEDIA CHANGED, SET CY
  3074 00001ABB C3                  <1> 	retn
  3075                              <1> MC_OUT:
  3076                              <1> 	;clc	; 08/07/2022		; NO MEDIA CHANGED, CLEAR CY
  3077 00001ABC C3                  <1> 	retn
  3078                              <1> 
  3079                              <1> ;-------------------------------------------------------------------------------
  3080                              <1> ; SEND_RATE
  3081                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3082                              <1> ; ON ENTRY:	DI = DRIVE #
  3083                              <1> ; ON EXIT:	NONE
  3084                              <1> ; REGISTERS ALTERED: DX
  3085                              <1> ;-------------------------------------------------------------------------------
  3086                              <1> SEND_RATE:
  3087                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5
  3088                              <1> 	;push	ax			; SAVE REG.
  3089                              <1> 	; 24/12/2021
  3090 00001ABD 50                  <1> 	push	eax
  3091 00001ABE 8025[64650000]3F    <1> 	and	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3092 00001AC5 8A87[67650000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3093 00001ACB 24C0                <1> 	and	al, SEND_MSK		; KEEP ONLY RATE BITS
  3094 00001ACD 0805[64650000]      <1> 	or	[LASTRATE], al		; SAVE NEW RATE FOR NEXT CHECK
  3095 00001AD3 C0C002              <1> 	rol	al, 2			; MOVE TO BIT OUTPUT POSITIONS
  3096 00001AD6 66BAF703            <1> 	mov	dx, 03F7h		; OUTPUT NEW DATA RATE
  3097 00001ADA EE                  <1> 	out	dx, al
  3098                              <1> 	;pop	ax			; RESTORE REG.
  3099                              <1> 	; 24/12/2021
  3100 00001ADB 58                  <1> 	pop	eax
  3101 00001ADC C3                  <1> 	RETn
  3102                              <1> 
  3103                              <1> ;-------------------------------------------------------------------------------
  3104                              <1> ; CHK_LASTRATE
  3105                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3106                              <1> ; ON ENTRY:
  3107                              <1> ;	EDI = DRIVE #
  3108                              <1> ; ON EXIT:
  3109                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3110                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3111                              <1> ; REGISTERS ALTERED: EDX
  3112                              <1> ;-------------------------------------------------------------------------------
  3113                              <1> CHK_LASTRATE:
  3114                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5
  3115                              <1> 	;push	ax			; SAVE REG.
  3116                              <1> 	; 24/12/2021
  3117 00001ADD 50                  <1> 	push	eax
  3118 00001ADE 8A25[64650000]      <1> 	mov	ah, [LASTRATE] ; 08/07/2022 (BugFix) 
  3119                              <1> 					; GET LAST DATA RATE SELECTED
  3120 00001AE4 8A87[67650000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3121 00001AEA 6625C0C0            <1>        	and	ax, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3122 00001AEE 38E0                <1> 	cmp	al, ah			; COMPARE TO PREVIOUSLY TRIED
  3123                              <1> 					; ZF = 1 RATE IS THE SAME
  3124                              <1> 	;pop	ax			; RESTORE REG.
  3125                              <1> 	; 24/12/2021
  3126 00001AF0 58                  <1> 	pop	eax
  3127 00001AF1 C3                  <1> 	RETn
  3128                              <1> 
  3129                              <1> ;-------------------------------------------------------------------------------
  3130                              <1> ; DMA_SETUP
  3131                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3132                              <1> ;
  3133                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3134                              <1> ;
  3135                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3136                              <1> ;-------------------------------------------------------------------------------
  3137                              <1> 
  3138                              <1> ; SI = Head #, # of Sectors or DASD Type
  3139                              <1> 
  3140                              <1> ; 22/08/2015
  3141                              <1> ; 08/02/2015 - Protected Mode Modification
  3142                              <1> ; 06/02/2015 - 07/02/2015
  3143                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3144                              <1> ; (DMA Addres = Physical Address)
  3145                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3146                              <1> ;
  3147                              <1> ; 04/02/2016 (clc)
  3148                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3149                              <1> ; 16/12/2014 (IODELAY)
  3150                              <1> 
  3151                              <1> DMA_SETUP:
  3152                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3153                              <1> ;; 20/02/2015
  3154 00001AF2 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3155                              <1> 	; 08/07/2022 - not needed for Retro UNIX 386 v1.1
  3156                              <1> 	;test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3157                              <1> 	;jnz	short dma_bnd_err_stc
  3158                              <1> 	; 24/12/2021
  3159 00001AF5 50                  <1> 	push	eax			; DMA command
  3160 00001AF6 52                  <1> 	push	edx			; *
  3161                              <1> 	;mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3162 00001AF7 B003                <1> 	mov	al, 3 ; 08/07/2022
  3163 00001AF9 E8A5020000          <1> 	call	GET_PARM		; 
  3164 00001AFE 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3165                              <1> 	;mov	ax, si			; Sector count
  3166                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3167                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3168                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3169                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3170                              <1> 	; 08/07/2022
  3171                              <1> 	; 24/12/2021
  3172                              <1> 	;mov	edx, esi
  3173 00001B00 29C0                <1> 	sub	eax, eax
  3174                              <1> 	;mov	ah, dl
  3175                              <1> 	;shr	eax, 1
  3176 00001B02 B080                <1> 	mov	al, 128
  3177 00001B04 D3E0                <1> 	shl	eax, cl
  3178                              <1> 	;
  3179 00001B06 48                  <1> 	dec	eax			; -1 FOR DMA VALUE
  3180 00001B07 89C1                <1> 	mov	ecx, eax
  3181 00001B09 5A                  <1> 	pop	edx			; *
  3182                              <1> 	; 24/12/2021
  3183 00001B0A 58                  <1> 	pop	eax
  3184                              <1> 	; 08/07/2022
  3185                              <1> 	;cmp	al, 42h
  3186                              <1>         ;jne	short NOT_VERF
  3187                              <1> 	;mov	edx, 0FF0000h
  3188                              <1> 	;jmp	short J33
  3189                              <1> ;NOT_VERF:
  3190 00001B0B 6601CA              <1> 	add	dx, cx			; check for (64K) overflow
  3191 00001B0E 723D                <1> 	jc	short dma_bnd_err
  3192                              <1> 	;
  3193 00001B10 6629CA              <1> 	sub	dx, cx			; Restore start address
  3194                              <1> J33:
  3195                              <1> 	; 08/07/2022
  3196 00001B13 FA                  <1> 	cli				; DISABLE INTERRUPTS DURING DMA SET-UP
  3197 00001B14 E60C                <1> 	out	DMA+12, al		; SET THE FIRST/LA5T F/F
  3198                              <1> 	IODELAY				; WAIT FOR I/O
  2160 00001B16 EB00                <2>  jmp short $+2
  2161 00001B18 EB00                <2>  jmp short $+2
  3199 00001B1A E60B                <1> 	out	DMA+11, al		; OUTPUT THE MODE BYTE
  3200 00001B1C 89D0                <1> 	mov	eax, edx		; Buffer address
  3201 00001B1E E604                <1> 	out	DMA+4, al		; OUTPUT LOW ADDRESS
  3202                              <1> 	IODELAY				; WAIT FOR I/O
  2160 00001B20 EB00                <2>  jmp short $+2
  2161 00001B22 EB00                <2>  jmp short $+2
  3203 00001B24 88E0                <1> 	mov	al, ah
  3204 00001B26 E604                <1> 	out	DMA+4, al		; OUTPUT HIGH ADDRESS
  3205 00001B28 C1E810              <1> 	shr	eax, 16
  3206                              <1> 	IODELAY				; I/O WAIT STATE
  2160 00001B2B EB00                <2>  jmp short $+2
  2161 00001B2D EB00                <2>  jmp short $+2
  3207 00001B2F E681                <1> 	out	081h, al		; OUTPUT highest BITS TO PAGE REGISTER
  3208                              <1> 	IODELAY
  2160 00001B31 EB00                <2>  jmp short $+2
  2161 00001B33 EB00                <2>  jmp short $+2
  3209                              <1> 	;mov	ax, cx			; Byte count - 1
  3210 00001B35 88C8                <1> 	mov	al, cl
  3211 00001B37 E605                <1> 	out	DMA+5, al		; LOW BYTE OF COUNT
  3212                              <1> 	IODELAY				; WAIT FOR I/O
  2160 00001B39 EB00                <2>  jmp short $+2
  2161 00001B3B EB00                <2>  jmp short $+2
  3213                              <1> 	;mov	al, ah
  3214 00001B3D 88E8                <1> 	mov	al, ch
  3215 00001B3F E605                <1> 	OUT	DMA+5, al		; HIGH BYTE OF COUNT
  3216                              <1> 	IODELAY
  2160 00001B41 EB00                <2>  jmp short $+2
  2161 00001B43 EB00                <2>  jmp short $+2
  3217 00001B45 FB                  <1> 	sti				; RE-ENABLE INTERRUPTS
  3218 00001B46 B002                <1> 	mov	al, 2			; MODE FOR 8237
  3219 00001B48 E60A                <1> 	OUT	DMA+10, al		; INITIALIZE THE DISKETTE CHANNEL
  3220                              <1> 
  3221 00001B4A F8                  <1> 	clc	; 04/02/2016
  3222 00001B4B C3                  <1> 	retn
  3223                              <1> 
  3224                              <1> dma_bnd_err_stc:
  3225 00001B4C F9                  <1> 	stc
  3226                              <1> dma_bnd_err:
  3227 00001B4D C605[5C650000]09    <1> 	mov	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3228 00001B54 C3                  <1> 	retn				; CY SET BY ABOVE IF ERROR
  3229                              <1> 
  3230                              <1> ;-------------------------------------------------------------------------------
  3231                              <1> ; NEC_INIT	
  3232                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3233                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3234                              <1> ;
  3235                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3236                              <1> ;
  3237                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3238                              <1> ;-------------------------------------------------------------------------------
  3239                              <1> NEC_INIT:
  3240                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3241                              <1> 	;push	ax			; SAVE NEC COMMAND
  3242                              <1> 	; 24/12/2021
  3243 00001B55 50                  <1> 	push	eax
  3244 00001B56 E888020000          <1> 	call	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3245                              <1> 
  3246                              <1> ;-----	DO THE SEEK OPERATION
  3247                              <1> 
  3248 00001B5B 8A6D01              <1> 	mov	ch, [ebp+1]		; CH = TRACK #
  3249 00001B5E E874030000          <1> 	call	SEEK			; MOVE TO CORRECT TRACK
  3250                              <1> 	;pop	ax			; RECOVER COMMAND
  3251                              <1> 	; 24/12/2021
  3252 00001B63 58                  <1> 	pop	eax
  3253 00001B64 721D                <1> 	jc	short ER_1		; ERROR ON SEEK
  3254 00001B66 BB[831B0000]        <1> 	mov	ebx, ER_1		; LOAD ERROR ADDRESS
  3255 00001B6B 53                  <1> 	push	ebx			; PUSH NEC_OUT ERROR RETURN
  3256                              <1> 
  3257                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3258                              <1> 
  3259 00001B6C E82D030000          <1> 	call	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3260 00001B71 89F0                <1> 	mov	eax, esi		; AH = HEAD #
  3261 00001B73 89FB                <1> 	mov	ebx, edi		; BL = DRIVE #
  3262 00001B75 C0E402              <1> 	sal	ah, 2			; MOVE IT TO BIT 2
  3263 00001B78 80E404              <1> 	and	ah, 00000100b		; ISOLATE THAT BIT
  3264 00001B7B 08DC                <1> 	or	ah, bl			; OR IN THE DRIVE NUMBER
  3265 00001B7D E81C030000          <1> 	call	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  3266 00001B82 5B                  <1> 	pop	ebx			; THROW AWAY ERROR RETURN
  3267                              <1> ER_1:
  3268 00001B83 C3                  <1> 	retn
  3269                              <1> 
  3270                              <1> ;-------------------------------------------------------------------------------
  3271                              <1> ; RWV_COM
  3272                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  3273                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  3274                              <1> ;
  3275                              <1> ; ON ENTRY:	EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  3276                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3277                              <1> ;-------------------------------------------------------------------------------
  3278                              <1> RWV_COM:
  3279                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3280 00001B84 B8[CE1B0000]        <1> 	mov	eax, ER_2		; LOAD ERROR ADDRESS
  3281 00001B89 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  3282 00001B8A 8A6501              <1> 	mov	ah, [ebp+1]		; OUTPUT TRACK #
  3283 00001B8D E80C030000          <1> 	call	NEC_OUTPUT
  3284 00001B92 89F0                <1> 	mov	eax, esi		; OUTPUT HEAD #
  3285 00001B94 E805030000          <1> 	call	NEC_OUTPUT
  3286 00001B99 8A6500              <1>         mov	ah, [ebp]		; OUTPUT SECTOR #
  3287 00001B9C E8FD020000          <1> 	CALL	NEC_OUTPUT
  3288                              <1> 	;mov	dl, 3			; BYTES/SECTOR PARAMETER FROM BLOCK
  3289 00001BA1 B003                <1> 	mov	al, 3 ; 08/07/2022
  3290 00001BA3 E8FB010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3291 00001BA8 E8F1020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3292                              <1> 	;mov	dl, 4			; EOT PARAMETER FROM BLOCK
  3293 00001BAD B004                <1> 	mov	al, 4 ; 08/07/2022
  3294 00001BAF E8EF010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3295 00001BB4 E8E5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3296 00001BB9 8A6305              <1>         mov	ah, [ebx+MD.GAP]	; GET GAP LENGTH
  3297                              <1> _R15:
  3298 00001BBC E8DD020000          <1> 	call	NEC_OUTPUT
  3299                              <1> 	;mov	dl, 6			; DTL PARAMETER PROM BLOCK
  3300 00001BC1 B006                <1> 	mov	al, 6 ; 08/07/2022
  3301 00001BC3 E8DB010000          <1> 	call	GET_PARM		; .. TO THE NEC
  3302 00001BC8 E8D1020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3303 00001BCD 58                  <1> 	pop	eax			; THROW AWAY ERROR EXIT
  3304                              <1> ER_2:
  3305 00001BCE C3                  <1> 	retn
  3306                              <1> 
  3307                              <1> ;-------------------------------------------------------------------------------
  3308                              <1> ; NEC_TERM
  3309                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  3310                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  3311                              <1> ;
  3312                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3313                              <1> ;-------------------------------------------------------------------------------
  3314                              <1> 
  3315                              <1> NEC_TERM:
  3316                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3317                              <1> 
  3318                              <1> ;-----	LET THE OPERATION HAPPEN
  3319                              <1> 
  3320 00001BCF 56                  <1> 	push	esi			; SAVE HEAD #, # OF SECTORS
  3321 00001BD0 E8D3030000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  3322 00001BD5 9C                  <1> 	pushfd	; 24/12/2021
  3323 00001BD6 E8FD030000          <1> 	call	RESULTS			; GET THE NEC STATUS
  3324 00001BDB 724B                <1> 	jc	short SET_END_POP
  3325 00001BDD 9D                  <1> 	popfd	; 24/12/2021
  3326 00001BDE 723E                <1> 	jc	short SET_END		; LOOK FOR ERROR
  3327                              <1> 
  3328                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  3329                              <1> 
  3330 00001BE0 FC                  <1> 	cld				; SET THE CORRECT DIRECTION
  3331 00001BE1 BE[5D650000]        <1> 	mov	esi, NEC_STATUS		; POINT TO STATUS FIELD
  3332 00001BE6 AC                  <1> 	lodsb				; GET ST0
  3333 00001BE7 24C0                <1> 	and	al, 11000000b		; TEST FOR NORMAL TERMINATION
  3334 00001BE9 7433                <1> 	jz	short SET_END
  3335 00001BEB 3C40                <1> 	cmp	al, 01000000b		; TEST FOR ABNORMAL TERMINATION
  3336 00001BED 7527                <1> 	jnz	short J18		; NOT ABNORMAL, BAD NEC
  3337                              <1> 
  3338                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  3339                              <1> 
  3340 00001BEF AC                  <1> 	lodsb				; GET ST1
  3341 00001BF0 D0E0                <1> 	sal	al, 1			; TEST FOR EDT FOUND
  3342 00001BF2 B404                <1> 	mov	ah, RECORD_NOT_FND
  3343 00001BF4 7222                <1> 	jc	short J19
  3344 00001BF6 C0E002              <1> 	sal	al, 2
  3345 00001BF9 B410                <1> 	mov	ah, BAD_CRC
  3346 00001BFB 721B                <1> 	jc	short J19
  3347 00001BFD D0E0                <1> 	sal	al, 1			; TEST FOR DMA OVERRUN
  3348 00001BFF B408                <1> 	mov	ah, BAD_DMA
  3349 00001C01 7215                <1> 	jc	short J19
  3350 00001C03 C0E002              <1> 	sal	al, 2			; TEST FOR RECORD NOT FOUND
  3351 00001C06 B404                <1> 	mov	ah, RECORD_NOT_FND
  3352 00001C08 720E                <1> 	jc	short J19
  3353 00001C0A D0E0                <1> 	sal	AL, 1
  3354 00001C0C B403                <1> 	mov	ah, WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  3355 00001C0E 7208                <1> 	jc	short J19
  3356 00001C10 D0E0                <1> 	sal	AL, 1			; TEST MISSING ADDRESS MARK
  3357 00001C12 B402                <1> 	mov	ah, BAD_ADDR_MARK
  3358 00001C14 7202                <1> 	jc	short J19
  3359                              <1> 
  3360                              <1> ;----- 	NEC MUST HAVE FAILED
  3361                              <1> J18:
  3362 00001C16 B420                <1> 	mov	ah, BAD_NEC
  3363                              <1> J19:
  3364 00001C18 0825[5C650000]      <1> 	or	[DSKETTE_STATUS], ah
  3365                              <1> SET_END:
  3366 00001C1E 803D[5C650000]01    <1> 	cmp	byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION
  3367 00001C25 F5                  <1> 	cmc
  3368 00001C26 5E                  <1> 	pop	esi
  3369 00001C27 C3                  <1> 	retn				; RESTORE HEAD #, # OF SECTORS
  3370                              <1> 
  3371                              <1> SET_END_POP:
  3372 00001C28 9D                  <1> 	popfd	; 24/12/2021
  3373 00001C29 EBF3                <1> 	jmp	short SET_END
  3374                              <1> 
  3375                              <1> ;-------------------------------------------------------------------------------
  3376                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  3377                              <1> ;-------------------------------------------------------------------------------
  3378                              <1> DSTATE:
  3379                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3380 00001C2B 803D[5C650000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3381 00001C32 753E                <1> 	jnz	short SETBAC		; IF ERROR JUMP
  3382 00001C34 808F[67650000]10    <1> 	or	byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  3383 00001C3B F687[67650000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ?
  3384 00001C42 752E                <1> 	jnz	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  3385 00001C44 8A87[67650000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3386 00001C4A 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3387 00001C4C 3C80                <1> 	cmp	al, RATE_250		; RATE 250 ?
  3388 00001C4E 751B                <1> 	jne	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  3389                              <1> 
  3390                              <1> ;----- 	CHECK IF IT IS 1.44M
  3391                              <1> 
  3392 00001C50 E845010000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3393                              <1> 	;;20/02/2015
  3394                              <1> 	;;jc	short M_12		; CMOS BAD
  3395 00001C55 7414                <1> 	jz	short M_12 ;; 20/02/2015
  3396 00001C57 3C04                <1> 	cmp	al, 4			; 1.44MB DRIVE ?
  3397 00001C59 7410                <1> 	je	short M_12		; YES
  3398                              <1> M_720:
  3399 00001C5B 80A7[67650000]FD    <1> 	and	byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  3400 00001C62 808F[67650000]04    <1> 	or	byte [DSK_STATE+edi], DRV_DET  ; MARK DRIVE DETERMINED
  3401 00001C69 EB07                <1> 	jmp	short SETBAC		; BACK
  3402                              <1> M_12:	
  3403 00001C6B 808F[67650000]06    <1> 	or	byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 
  3404                              <1> 					; TURN ON DETERMINED & FMT CAPA
  3405                              <1> SETBAC:
  3406 00001C72 C3                  <1> 	retn
  3407                              <1> 
  3408                              <1> ;-------------------------------------------------------------------------------
  3409                              <1> ; RETRY	
  3410                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  3411                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  3412                              <1> ;
  3413                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  3414                              <1> ;-------------------------------------------------------------------------------
  3415                              <1> RETRY:
  3416                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3417 00001C73 803D[5C650000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION
  3418 00001C7A 7444                <1> 	je	short NO_RETRY		; SUCCESSFUL OPERATION
  3419 00001C7C 803D[5C650000]80    <1> 	cmp	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY
  3420 00001C83 743B                <1> 	je	short NO_RETRY
  3421 00001C85 8AA7[67650000]      <1> 	mov	ah, [DSK_STATE+edi]	; GET MEDIA STATE OF DRIVE
  3422 00001C8B F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED/DETERMINED ?
  3423 00001C8E 7530                <1> 	jnz	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  3424 00001C90 80E4C0              <1> 	and	ah, RATE_MSK		; ISOLATE RATE
  3425 00001C93 8A2D[64650000]      <1> 	mov	ch, [LASTRATE]		; GET START OPERATION STATE
  3426 00001C99 C0C504              <1> 	rol	ch, 4			; TO CORRESPONDING BITS
  3427 00001C9C 80E5C0              <1> 	and	ch, RATE_MSK		; ISOLATE RATE BITS
  3428 00001C9F 38E5                <1> 	cmp	ch, ah			; ALL RATES TRIED
  3429 00001CA1 741D                <1> 	je	short NO_RETRY		; IF YES, THEN TRUE ERROR
  3430                              <1> 
  3431                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  3432                              <1> ;	 00000000B (500) -> 10000000B	(250)
  3433                              <1> ;	 10000000B (250) -> 01000000B	(300)
  3434                              <1> ;	 01000000B (300) -> 00000000B	(500)
  3435                              <1> 
  3436 00001CA3 80FC01              <1> 	cmp	ah, RATE_500+1		; SET CY FOR RATE 500
  3437 00001CA6 D0DC                <1> 	rcr	ah, 1			; TO NEXT STATE
  3438 00001CA8 80E4C0              <1> 	and	ah, RATE_MSK		; KEEP ONLY RATE BITS
  3439 00001CAB 80A7[67650000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP)
  3440                              <1> 					; RATE, DBL STEP OFF
  3441 00001CB2 08A7[67650000]      <1> 	or	[DSK_STATE+edi], ah	; TURN ON NEW RATE
  3442 00001CB8 C605[5C650000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY
  3443 00001CBF F9                  <1> 	stc				; SET CARRY FOR RETRY
  3444                              <1> NO_RETRY:	; 08/07/2022
  3445 00001CC0 C3                  <1> 	retn				; RETRY RETURN
  3446                              <1> 
  3447                              <1> ;NO_RETRY:
  3448                              <1> 	;clc				; CLEAR CARRY NO RETRY
  3449                              <1> 	;RETn				; NO RETRY RETURN
  3450                              <1> 
  3451                              <1> ;-------------------------------------------------------------------------------
  3452                              <1> ; NUM_TRANS
  3453                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  3454                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  3455                              <1> ;
  3456                              <1> ; ON ENTRY:	[BP+1] = TRACK
  3457                              <1> ;		SI-HI  = HEAD
  3458                              <1> ;		[BP]   = START SECTOR
  3459                              <1> ;
  3460                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  3461                              <1> ;-------------------------------------------------------------------------------
  3462                              <1> NUM_TRANS:
  3463                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3464 00001CC1 30C0                <1> 	xor	al, al			; CLEAR FOR ERROR
  3465 00001CC3 803D[5C650000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3466                              <1> 	; 24/12/2021
  3467 00001CCA 752B                <1> 	jnz	short NT_OUT		; IF ERROR 0 TRANSFERRED
  3468                              <1> 	;mov	dl, 4			; SECTORS/TRACK OFFSET TO DL
  3469 00001CCC B004                <1> 	mov	al, 4 ; 08/07/2022
  3470 00001CCE E8D0000000          <1> 	call	GET_PARM		; AH = SECTORS/TRACK
  3471 00001CD3 8A1D[62650000]      <1> 	mov	bl, [NEC_STATUS+5]	; GET ENDING SECTOR
  3472 00001CD9 89F1                <1> 	mov	ecx, esi		; CH = HEAD # STARTED
  3473 00001CDB 3A2D[61650000]      <1> 	cmp	ch, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  3474 00001CE1 750D                <1> 	jnz	short DIF_HD		; IF ON SAME HEAD, THEN NO ADJUST
  3475 00001CE3 8A2D[60650000]      <1> 	mov	ch, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  3476 00001CE9 3A6D01              <1> 	cmp	ch, [ebp+1]		; IS IT ASKED FOR TRACK
  3477 00001CEC 7404                <1> 	jz	short SAME_TRK		; IF SAME TRACK NO INCREASE
  3478 00001CEE 00E3                <1> 	add	bl, ah			; ADD SECTORS/TRACK
  3479                              <1> DIF_HD:
  3480 00001CF0 00E3                <1> 	add	bl, ah			; ADD SECTORS/TRACK
  3481                              <1> SAME_TRK:
  3482 00001CF2 2A5D00              <1> 	sub	bl, [ebp]		; SUBTRACT START FROM END
  3483 00001CF5 88D8                <1> 	mov	al, bl			; TO AL
  3484                              <1> NT_OUT:
  3485 00001CF7 C3                  <1> 	retn
  3486                              <1> 
  3487                              <1> ;-------------------------------------------------------------------------------
  3488                              <1> ; SETUP_DBL
  3489                              <1> ;	CHECK DOUBLE STEP.
  3490                              <1> ;
  3491                              <1> ; ON ENTRY :	EDI = DRIVE #
  3492                              <1> ;
  3493                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  3494                              <1> ;-------------------------------------------------------------------------------
  3495                              <1> SETUP_DBL:
  3496                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3497 00001CF8 8AA7[67650000]      <1> 	mov	ah, [DSK_STATE+edi]	; ACCESS STATE
  3498 00001CFE F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED STATE ?
  3499 00001D01 7578                <1> 	jnz	short NO_DBL		; IF ESTABLISHED THEN DOUBLE DONE
  3500                              <1> 
  3501                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  3502                              <1> 
  3503 00001D03 C605[59650000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  3504 00001D0A E8D4000000          <1> 	call	MOTOR_ON		; ENSURE MOTOR STAY ON
  3505 00001D0F B500                <1> 	mov	CH, 0			; LOAD TRACK 0
  3506 00001D11 E8C1010000          <1> 	call	SEEK			; SEEK TO TRACK 0
  3507 00001D16 E862000000          <1> 	call	READ_ID			; READ ID FUNCTION
  3508 00001D1B 7243                <1> 	jc	short SD_ERR		; IF ERROR NO TRACK 0
  3509                              <1> 
  3510                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  3511                              <1> 
  3512 00001D1D 66B95004            <1> 	mov	cx, 0450h 		; START, MAX TRACKS
  3513 00001D21 F687[67650000]01    <1> 	test	byte [DSK_STATE+edi],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  3514 00001D28 7402                <1> 	jz	short CNT_OK		; IF NOT COUNT IS SETUP
  3515 00001D2A B1A0                <1> 	mov	cl, 0A0h		; MAXIMUM TRACK 1.2 MB
  3516                              <1> 
  3517                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  3518                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  3519                              <1> ;	THEN SET DOUBLE STEP ON.
  3520                              <1> 
  3521                              <1> CNT_OK:
  3522 00001D2C C605[5B650000]FF    <1>        	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 
  3523                              <1> 	; 24/12/2021
  3524 00001D33 51                  <1> 	push	ecx			; SAVE TRACK, COUNT
  3525 00001D34 C605[5C650000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS
  3526 00001D3B 31C0                <1> 	xor	eax, eax		; CLEAR EAX
  3527 00001D3D D0ED                <1> 	shr	ch, 1			; HALVE TRACK, CY = HEAD
  3528 00001D3F C0D003              <1> 	rcl	al, 3			; AX = HEAD IN CORRECT BIT
  3529                              <1> 	; 24/12/2021
  3530 00001D42 50                  <1> 	push	eax			; SAVE HEAD
  3531 00001D43 E88F010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  3532                              <1> 	; 24/12/2021
  3533 00001D48 58                  <1> 	pop	eax			; RESTORE HEAD
  3534 00001D49 09C7                <1> 	or	edi, eax		; DI = HEAD OR'ED DRIVE
  3535 00001D4B E82D000000          <1> 	call	READ_ID			; READ ID HEAD 0
  3536 00001D50 9C                  <1> 	pushf				; SAVE RETURN FROM READ_ID
  3537 00001D51 6681E7FB00          <1> 	and	di, 11111011b		; TURN OFF HEAD 1 BIT
  3538 00001D56 9D                  <1> 	popf				; RESTORE ERROR RETURN
  3539                              <1> 	; 24/12/2021
  3540 00001D57 59                  <1> 	pop	ecx			; RESTORE COUNT
  3541 00001D58 7308                <1> 	jnc	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  3542 00001D5A FEC5                <1> 	inc	ch			; INC FOR NEXT TRACK
  3543 00001D5C 38CD                <1> 	cmp	CH, CL			; REACHED MAXIMUM YET
  3544 00001D5E 75CC                <1> 	jnz	short CNT_OK		; CONTINUE TILL ALL TRIED
  3545                              <1> 
  3546                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  3547                              <1> 
  3548                              <1> SD_ERR:	
  3549 00001D60 F9                  <1> 	stc				; SET CARRY FOR ERROR
  3550 00001D61 C3                  <1> 	retn				; SETUP_DBL ERROR EXIT
  3551                              <1> 
  3552                              <1> DO_CHK:
  3553 00001D62 8A0D[60650000]      <1> 	mov	cl, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  3554 00001D68 888F[69650000]      <1> 	mov	[DSK_TRK+edi], cl	; STORE TRACK NUMBER
  3555 00001D6E D0ED                <1> 	shr	ch, 1			; HALVE TRACK
  3556 00001D70 38CD                <1> 	cmp	ch, cl			; IS IT THE SAME AS ASKED FOR TRACK
  3557 00001D72 7407                <1> 	jz	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  3558 00001D74 808F[67650000]20    <1> 	or	byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  3559                              <1> NO_DBL:
  3560 00001D7B F8                  <1> 	clc				; CLEAR ERROR FLAG
  3561 00001D7C C3                  <1> 	retn
  3562                              <1> 
  3563                              <1> ;-------------------------------------------------------------------------------
  3564                              <1> ; READ_ID
  3565                              <1> ;	READ ID FUNCTION.
  3566                              <1> ;
  3567                              <1> ; ON ENTRY:	EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  3568                              <1> ;
  3569                              <1> ; ON EXIT: 	EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  3570                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3571                              <1> ;-------------------------------------------------------------------------------
  3572                              <1> READ_ID:
  3573                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3574 00001D7D B8[991D0000]        <1> 	mov	eax, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  3575 00001D82 50                  <1> 	push	eax
  3576 00001D83 B44A                <1> 	mov	ah, 4Ah			; READ ID COMMAND
  3577 00001D85 E814010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3578 00001D8A 89F8                <1> 	mov	eax, edi		; DRIVE # TO AH, HEAD 0
  3579 00001D8C 88C4                <1> 	mov	ah, al
  3580 00001D8E E80B010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3581 00001D93 E837FEFFFF          <1> 	call	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  3582 00001D98 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3583                              <1> ER_3:
  3584 00001D99 C3                  <1> 	retn
  3585                              <1> 
  3586                              <1> ;-------------------------------------------------------------------------------
  3587                              <1> ; CMOS_TYPE
  3588                              <1> ;	RETURNS CMOS DISKETTE TYPE
  3589                              <1> ;
  3590                              <1> ; ON ENTRY:	EDI = DRIVE #
  3591                              <1> ;
  3592                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  3593                              <1> ;-------------------------------------------------------------------------------
  3594                              <1> 
  3595                              <1> CMOS_TYPE: ; 11/12/2014
  3596                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3597 00001D9A 8A87[CE5F0000]      <1> 	mov	al, [edi+fd0_type] ; diskette type
  3598 00001DA0 20C0                <1> 	and 	al, al ; 18/12/2014
  3599 00001DA2 C3                  <1> 	retn
  3600                              <1> 
  3601                              <1> ;-------------------------------------------------------------------------------
  3602                              <1> ; GET_PARM
  3603                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  3604                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  3605                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  3606                              <1> ;	THE PARAMETER IN DL.
  3607                              <1> ;
  3608                              <1> ; ON ENTRY:	AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022
  3609                              <1> ;
  3610                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  3611                              <1> ;		AL DESTROYED
  3612                              <1> ;-------------------------------------------------------------------------------
  3613                              <1> GET_PARM:
  3614                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3615                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  3616 00001DA3 56                  <1> 	push	esi
  3617 00001DA4 53                  <1> 	push	ebx			; SAVE EBX	
  3618 00001DA5 0FB6D8              <1> 	movzx	ebx, al			; EBX = INDEX
  3619                              <1>    	; 17/12/2014
  3620 00001DA8 66A1[C15F0000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  3621 00001DAE 38E0                <1> 	cmp	al, ah
  3622 00001DB0 7425                <1> 	je	short gpndc
  3623 00001DB2 A2[C25F0000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  3624 00001DB7 53                  <1> 	push	ebx ; 08/02/2015
  3625 00001DB8 88C3                <1> 	mov	bl, al 
  3626                              <1> 	; 11/12/2014
  3627 00001DBA 8A83[CE5F0000]      <1> 	mov	al, [ebx+fd0_type]	; Drive type (0,1,2,3,4)
  3628                              <1> 	; 18/12/2014
  3629 00001DC0 20C0                <1> 	and	al, al
  3630 00001DC2 7507                <1> 	jnz	short gpdtc
  3631 00001DC4 BB[AB5F0000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  3632 00001DC9 EB05                <1>         jmp     short gpdpu
  3633                              <1> gpdtc:	
  3634 00001DCB E887FBFFFF          <1> 	call	DR_TYPE_CHECK
  3635                              <1> 	; cf = 1 -> EBX points to 1.44MB fd parameter table (default)
  3636                              <1> gpdpu:
  3637 00001DD0 891D[485F0000]      <1> 	mov	[DISK_POINTER], ebx
  3638 00001DD6 5B                  <1> 	pop	ebx
  3639                              <1> gpndc:
  3640 00001DD7 8B35[485F0000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  3641 00001DDD 8A241E              <1> 	mov	ah, [esi+ebx]		; GET THE WORD
  3642 00001DE0 5B                  <1> 	pop	ebx			; RESTORE EBX
  3643 00001DE1 5E                  <1> 	pop	esi
  3644 00001DE2 C3                  <1> 	retn
  3645                              <1> 
  3646                              <1> ;-------------------------------------------------------------------------------
  3647                              <1> ; MOTOR_ON
  3648                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  3649                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  3650                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  3651                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  3652                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  3653                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  3654                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  3655                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  3656                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  3657                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  3658                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  3659                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  3660                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  3661                              <1> ;
  3662                              <1> ; ON ENTRY:	EDI = DRIVE #
  3663                              <1> ; ON EXIT:	EAX, ECX, EDX DESTROYED
  3664                              <1> ;-------------------------------------------------------------------------------
  3665                              <1> MOTOR_ON:
  3666                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3667 00001DE3 53                  <1> 	push	ebx			; SAVE REG.
  3668 00001DE4 E825000000          <1> 	call	TURN_ON			; TURN ON MOTOR
  3669 00001DE9 7221                <1> 	jc	short MOT_IS_ON		; IF CY=1 NO WAIT
  3670                              <1> 	;call	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3671                              <1> 	; 08/07/2022
  3672 00001DEB E8D2FBFFFF          <1> 	call	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  3673                              <1> 	;call	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  3674                              <1> 	;jc	short MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  3675                              <1> M_WAIT:
  3676                              <1> 	;mov	dl,10			; GET THE MOTOR WAIT PARAMETER
  3677 00001DF0 B00A                <1> 	mov	al, 10 ; 08/07/2022
  3678 00001DF2 E8ACFFFFFF          <1> 	call	GET_PARM
  3679                              <1> 	; 08/07/2022			; AH = MOTOR WAIT PARAMETER
  3680 00001DF7 80FC08              <1> 	cmp	ah, 8			; SEE IF AT LEAST A SECOND IS SPECIFIED			
  3681                              <1> 	;jae	short GP2		; IF YES, CONTINUE
  3682 00001DFA 7302                <1> 	jae	short J13
  3683 00001DFC B408                <1> 	mov	ah, 8			; ONE SECOND WAIT FOR MOTOR START UP
  3684                              <1> 
  3685                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  3686                              <1> GP2:	
  3687                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  3688                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  3689 00001DFE B95E200000          <1> 	mov	ecx, 8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  3690 00001E03 E8B0F6FFFF          <1> 	call	WAITF			; GO TO FIXED WAIT ROUTINE
  3691                              <1> 	;dec	al			; DECREMENT TIME VALUE
  3692 00001E08 FECC                <1> 	dec	ah
  3693 00001E0A 75F2                <1> 	jnz	short J13		; ARE WE DONE YET
  3694                              <1> MOT_IS_ON:
  3695 00001E0C 5B                  <1> 	pop	ebx			; RESTORE REG.
  3696 00001E0D C3                  <1> 	retn
  3697                              <1> 
  3698                              <1> ;-------------------------------------------------------------------------------
  3699                              <1> ; TURN_ON
  3700                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  3701                              <1> ;
  3702                              <1> ; ON ENTRY:	EDI = DRIVE #
  3703                              <1> ;
  3704                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  3705                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  3706                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  3707                              <1> ;-------------------------------------------------------------------------------
  3708                              <1> TURN_ON:
  3709                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3710 00001E0E 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  3711 00001E10 88D9                <1> 	mov	cl, bl			; CL = DRIVE #
  3712 00001E12 C0C304              <1> 	rol	bl, 4			; BL = DRIVE SELECT
  3713 00001E15 FA                  <1> 	cli				; NO INTERRUPTS WHILE DETERMINING STATUS
  3714 00001E16 C605[5B650000]FF    <1> 	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION
  3715 00001E1D A0[5A650000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3716 00001E22 2430                <1> 	and	al, 00110000b		; KEEP ONLY DRIVE SELECT BITS
  3717 00001E24 B401                <1> 	mov	ah, 1			; MASK FOR DETERMINING MOTOR BIT
  3718 00001E26 D2E4                <1> 	shl	ah, cl			; AH = MOTOR ON, A=00000001, B=00000010
  3719                              <1> 
  3720                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  3721                              <1> ;  BL = DRIVE SELECT DESIRED
  3722                              <1> ;  AH = MOTOR ON MASK DESIRED
  3723                              <1> 
  3724 00001E28 38D8                <1> 	cmp	al, bl			; REQUESTED DRIVE ALREADY SELECTED ?
  3725 00001E2A 7508                <1> 	jne	short TURN_IT_ON	; IF NOT SELECTED JUMP
  3726 00001E2C 8425[5A650000]      <1> 	test	ah, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  3727 00001E32 7535                <1> 	jnz	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  3728                              <1> 
  3729                              <1> TURN_IT_ON:
  3730 00001E34 08DC                <1> 	or	ah, bl			; AH = DRIVE SELECT AND MOTOR ON
  3731 00001E36 8A3D[5A650000]      <1> 	mov	bh, [MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  3732 00001E3C 80E70F              <1> 	and	bh, 00001111b		; KEEP ONLY MOTOR BITS
  3733 00001E3F 8025[5A650000]CF    <1> 	and	byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT
  3734 00001E46 0825[5A650000]      <1> 	or	[MOTOR_STATUS], ah	; OR IN DRIVE SELECTED AND MOTOR ON
  3735 00001E4C A0[5A650000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3736 00001E51 88C3                <1> 	mov	bl, al			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  3737 00001E53 80E30F              <1> 	and	bl, 00001111b		; KEEP ONLY MOTOR BITS
  3738 00001E56 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3739 00001E57 243F                <1> 	and	al, 00111111b		; STRIP AWAY UNWANTED BITS
  3740 00001E59 C0C004              <1> 	rol	al, 4			; PUT BITS IN DESIRED POSITIONS
  3741 00001E5C 0C0C                <1> 	or	al, 00001100b		; NO RESET, ENABLE DMA/INTERRUPT
  3742 00001E5E 66BAF203            <1> 	mov	dx, 03F2h		; SELECT DRIVE AND TURN ON MOTOR
  3743 00001E62 EE                  <1> 	out	dx, al
  3744 00001E63 38FB                <1> 	cmp	bl,  bh			; NEW MOTOR TURNED ON ?
  3745                              <1> 	;je	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  3746 00001E65 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  3747 00001E67 F8                  <1> 	clc				; (re)SET CARRY MEANING WAIT
  3748 00001E68 C3                  <1> 	retn
  3749                              <1> 
  3750                              <1> NO_MOT_WAIT:
  3751 00001E69 FB                  <1> 	sti
  3752                              <1> no_mot_w1: ; 27/02/2015
  3753 00001E6A F9                  <1> 	stc				; SET NO WAIT REQUIRED
  3754                              <1> 	;sti				; INTERRUPTS BACK ON
  3755 00001E6B C3                  <1> 	retn
  3756                              <1> 
  3757                              <1> ;-------------------------------------------------------------------------------
  3758                              <1> ; HD_WAIT
  3759                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  3760                              <1> ;
  3761                              <1> ; ON ENTRY:	DI = DRIVE #
  3762                              <1> ;
  3763                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  3764                              <1> ;-------------------------------------------------------------------------------
  3765                              <1> HD_WAIT:
  3766                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3767                              <1> 	;mov	dl, 9			; GET HEAD SETTLE PARAMETER
  3768 00001E6C B009                <1> 	mov	al, 9	; 08/07/2022
  3769 00001E6E E830FFFFFF          <1> 	CALL	GET_PARM
  3770 00001E73 08E4                <1> 	or	ah, ah	; 17/12/2014	; CHECK FOR ANY WAIT?
  3771 00001E75 7519                <1> 	jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3772 00001E77 F605[5A650000]80    <1>         test	byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION
  3773                              <1> 	;jz	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  3774                              <1> 	;or	ah, ah			; CHECK FOR ANY WAIT?
  3775                              <1> 	;jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3776 00001E7E 741D                <1> 	jz	short HW_DONE
  3777 00001E80 B40F                <1> 	mov	ah, HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  3778 00001E82 8A87[67650000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3779 00001E88 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3780 00001E8A 3C80                <1> 	cmp	al, RATE_250		; 1.2 M DRIVE ?
  3781 00001E8C 7502                <1> 	jnz	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  3782                              <1> ;GP3:
  3783 00001E8E B414                <1> 	mov	ah, HD320_SETTLE		; USE 320/360 HEAD SETTLE
  3784                              <1> ;	jmp	short DO_WAT
  3785                              <1> 
  3786                              <1> ;ISNT_WRITE:
  3787                              <1> ;	or	ah, ah			; CHECK FOR NO WAIT
  3788                              <1> ;	jz	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  3789                              <1> 
  3790                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  3791                              <1> DO_WAT:
  3792                              <1> ;	mov	al, ah			; AL = # MILLISECONDS
  3793                              <1> ;	;xor	ah, ah			; AX = # MILLISECONDS
  3794                              <1> J29:					; 	1 MILLISECOND LOOP
  3795                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  3796                              <1> 	;mov	ecx, 66			; COUNT AT 15.085737 US PER COUNT
  3797                              <1> 	; 08/07/2022
  3798 00001E90 29C9                <1> 	sub	ecx, ecx
  3799 00001E92 B142                <1> 	mov	cl, 66
  3800 00001E94 E81FF6FFFF          <1> 	call	WAITF			; DELAY FOR 1 MILLISECOND
  3801                              <1> 	;dec	al			; DECREMENT THE COUNT
  3802 00001E99 FECC                <1> 	dec	ah
  3803 00001E9B 75F3                <1> 	jnz	short J29		; DO AL MILLISECOND # OF TIMES
  3804                              <1> HW_DONE:
  3805 00001E9D C3                  <1> 	retn
  3806                              <1> 
  3807                              <1> ;-------------------------------------------------------------------------------
  3808                              <1> ; NEC_OUTPUT
  3809                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  3810                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  3811                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  3812                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  3813                              <1> ; 
  3814                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  3815                              <1> ;
  3816                              <1> ; ON EXIT:	CY = 0  SUCCESS
  3817                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  3818                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  3819                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  3820                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  3821                              <1> ;
  3822                              <1> ;		EAX, ECX, EDX DESTROYED
  3823                              <1> ;-------------------------------------------------------------------------------
  3824                              <1> 
  3825                              <1> ; 09/12/2014 [Erdogan Tan] 
  3826                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  3827                              <1> ; Diskette Drive Controller Status Register (3F4h)
  3828                              <1> ;	This read only register facilitates the transfer of data between
  3829                              <1> ;	the system microprocessor and the controller.
  3830                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  3831                              <1> ;	  with the system micrprocessor.
  3832                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  3833                              <1> ;	  the transfer is to the controller.
  3834                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  3835                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  3836                              <1> ; Bit 3 - Reserved.
  3837                              <1> ; Bit 2 - Reserved.
  3838                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3839                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3840                              <1> 
  3841                              <1> ; Data Register (3F5h)
  3842                              <1> ; This read/write register passes data, commands and parameters, and provides
  3843                              <1> ; diskette status information.
  3844                              <1>   		
  3845                              <1> NEC_OUTPUT:
  3846                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3847                              <1> 	;push	ebx			; SAVE REG.
  3848 00001E9E BAF4030000          <1> 	mov	edx, 03F4h		; STATUS PORT
  3849                              <1> 	;xor	ecx, ecx		; COUNT FOR TIME OUT
  3850                              <1> 	; 16/12/2014
  3851                              <1> 	; waiting for (max.) 0.5 seconds
  3852                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  3853                              <1> 	;
  3854                              <1> 	; 17/12/2014
  3855                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  3856                              <1> 	;
  3857                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  3858                              <1> 	;		go on.
  3859                              <1> 	;INPUT:
  3860                              <1> 	;	AH=Mask for isolation bits.
  3861                              <1> 	;	AL=pattern to look for.
  3862                              <1> 	;	DX=Port to test for
  3863                              <1> 	;	ECX=Number of memory refresh periods to delay.
  3864                              <1> 	;	     (normally 30 microseconds per period.)
  3865                              <1> 	;
  3866                              <1> 	;WFP_SHORT:  
  3867                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  3868                              <1> 	;
  3869                              <1> 
  3870 00001EA3 B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  3871                              <1> ;
  3872                              <1> ;WFPS_OUTER_LP:
  3873                              <1> ;	;
  3874                              <1> ;WFPS_CHECK_PORT:
  3875                              <1> J23:
  3876 00001EA8 EC                  <1> 	in	al, dx			; GET STATUS
  3877 00001EA9 24C0                <1> 	and	al, 11000000b		; KEEP STATUS AND DIRECTION
  3878 00001EAB 3C80                <1> 	cmp	al, 10000000b		; STATUS 1 AND DIRECTION 0 ?
  3879 00001EAD 7418                <1> 	jz	short J27		; STATUS AND DIRECTION OK
  3880                              <1> WFPS_HI:
  3881 00001EAF E461                <1> 	in	al, PORT_B	; 061h	; SYS1	; wait for hi to lo
  3882 00001EB1 A810                <1> 	test	al, 010h		; transition on memory
  3883 00001EB3 75FA                <1> 	jnz	short WFPS_HI		; refresh.
  3884                              <1> WFPS_LO:
  3885 00001EB5 E461                <1> 	in	al, PORT_B		; SYS1
  3886 00001EB7 A810                <1> 	test	al, 010h
  3887 00001EB9 74FA                <1> 	jz	short WFPS_LO
  3888                              <1> 	;loop	short WFPS_CHECK_PORT
  3889 00001EBB E2EB                <1> 	loop	J23	; 27/02/2015	; REPEAT TILL DELAY FINISHED
  3890                              <1> 
  3891                              <1> 	; fail
  3892                              <1> 
  3893                              <1> ;WFPS_TIMEOUT:
  3894                              <1> 
  3895                              <1> ;-----	FALL THRU TO ERROR RETURN
  3896                              <1> 
  3897 00001EBD 800D[5C650000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  3898                              <1> 	;pop	ebx			; RESTORE REG.
  3899 00001EC4 58                  <1> 	pop	eax ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  3900 00001EC5 F9                  <1> 	stc				; INDICATE ERROR TO CALLER
  3901 00001EC6 C3                  <1> 	retn
  3902                              <1> 
  3903                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  3904                              <1> 
  3905                              <1> J27:	
  3906 00001EC7 88E0                <1> 	mov	al, ah			; GET BYTE TO OUTPUT
  3907 00001EC9 42                  <1> 	inc	edx			; DATA PORT = STATUS PORT + 1
  3908 00001ECA EE                  <1> 	out	dx, al			; OUTPUT THE BYTE
  3909                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  3910                              <1> 	; 27/02/2015
  3911 00001ECB 9C                  <1> 	pushfd	; 24/12/2021		; SAVE FLAGS
  3912                              <1> 	;mov	ecx, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  3913 00001ECC 29C9                <1> 	sub	ecx, ecx
  3914 00001ECE B103                <1> 	mov	cl, 3 ; 24/12/2021
  3915 00001ED0 E8E3F5FFFF          <1> 	call 	WAITF			; NEC FLAGS UPDATE CYCLE
  3916 00001ED5 9D                  <1> 	popfd	; 24/12/2021		; RESTORE FLAGS FOR EXIT
  3917                              <1> 	;pop	ebx			; RESTORE REG
  3918 00001ED6 C3                  <1> 	retn				; CY = 0 FROM TEST INSTRUCTION
  3919                              <1> 
  3920                              <1> ;-------------------------------------------------------------------------------
  3921                              <1> ; SEEK
  3922                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  3923                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  3924                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  3925                              <1> ;
  3926                              <1> ; ON ENTRY:	EDI = DRIVE #
  3927                              <1> ;		CH = TRACK #
  3928                              <1> ;
  3929                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  3930                              <1> ;		AX,BX,CX DX DESTROYED
  3931                              <1> ;-------------------------------------------------------------------------------
  3932                              <1> SEEK:
  3933                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3934 00001ED7 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  3935 00001ED9 B001                <1> 	mov	al, 1			; ESTABLISH MASK FOR RECALIBRATE TEST
  3936 00001EDB 86CB                <1> 	xchg	cl, bl			; SET DRIVE VALUE INTO CL
  3937 00001EDD D2C0                <1> 	rol	al, cl			; SHIFT MASK BY THE DRIVE VALUE
  3938 00001EDF 86CB                <1> 	xchg	cl, bl			; RECOVER DRIVE VALUE
  3939 00001EE1 8405[59650000]      <1> 	test	al, [SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  3940 00001EE7 7526                <1> 	jnz	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  3941                              <1> 
  3942 00001EE9 0805[59650000]      <1> 	or	[SEEK_STATUS], al	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  3943 00001EEF E862000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  3944 00001EF4 730E                <1> 	jnc	short AFT_RECAL		; RECALIBRATE DONE
  3945                              <1> 
  3946                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  3947                              <1> 
  3948 00001EF6 C605[5C650000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS
  3949 00001EFD E854000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  3950 00001F02 7251                <1> 	jc	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  3951                              <1> 
  3952                              <1> AFT_RECAL:
  3953 00001F04 C687[69650000]00    <1> 	mov	byte [DSK_TRK+edi], 0	; SAVE NEW CYLINDER AS PRESENT POSITION
  3954 00001F0B 08ED                <1> 	or	ch, ch			; CHECK FOR SEEK TO TRACK 0
  3955 00001F0D 743F                <1> 	jz	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  3956                              <1> 
  3957                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  3958                              <1> 
  3959 00001F0F F687[67650000]20    <1> J28A:	test	byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  3960 00001F16 7402                <1> 	jz	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  3961 00001F18 D0E5                <1> 	shl	ch, 1			; DOUBLE NUMBER OF STEP TO TAKE
  3962                              <1> 
  3963 00001F1A 3AAF[69650000]      <1> _R7:	cmp	ch, [DSK_TRK+edi]	; SEE IF ALREADY AT THE DESIRED TRACK
  3964 00001F20 7433                <1> 	je	short RB		; IF YES, DO NOT NEED TO SEEK
  3965                              <1> 
  3966 00001F22 BA[551F0000]        <1> 	mov	edx, NEC_ERR		; LOAD RETURN ADDRESS
  3967 00001F27 52                  <1> 	push	edx ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  3968 00001F28 88AF[69650000]      <1> 	mov	[DSK_TRK+edi], CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  3969 00001F2E B40F                <1> 	mov	AH, 0Fh			; SEEK COMMAND TO NEC
  3970 00001F30 E869FFFFFF          <1> 	call	NEC_OUTPUT
  3971 00001F35 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  3972 00001F37 88DC                <1> 	mov	ah, bl			; OUTPUT DRIVE NUMBER
  3973 00001F39 E860FFFFFF          <1> 	call	NEC_OUTPUT
  3974 00001F3E 8AA7[69650000]      <1> 	mov	ah, [DSK_TRK+edi]	; GET CYLINDER NUMBER
  3975 00001F44 E855FFFFFF          <1> 	call	NEC_OUTPUT
  3976 00001F49 E827000000          <1> 	call	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  3977                              <1> 
  3978                              <1> ;-----	WAIT FOR HEAD SETTLE
  3979                              <1> 
  3980                              <1> DO_WAIT:
  3981 00001F4E 9C                  <1> 	pushfd	; 24/12/2021		; SAVE STATUS
  3982 00001F4F E818FFFFFF          <1> 	call	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  3983 00001F54 9D                  <1> 	popfd	; 24/12/2021		; RESTORE STATUS
  3984                              <1> RB:
  3985                              <1> NEC_ERR:
  3986                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  3987                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  3988 00001F55 C3                  <1> 	retn				; RETURN TO CALLER
  3989                              <1> 
  3990                              <1> ;-------------------------------------------------------------------------------
  3991                              <1> ; RECAL
  3992                              <1> ;	RECALIBRATE DRIVE
  3993                              <1> ;
  3994                              <1> ; ON ENTRY:	EDI = DRIVE #
  3995                              <1> ;
  3996                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  3997                              <1> ;-------------------------------------------------------------------------------
  3998                              <1> RECAL:
  3999                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4000                              <1> 	;push	cx
  4001                              <1> 	; 24/12/2021
  4002 00001F56 51                  <1> 	push	ecx
  4003 00001F57 B8[731F0000]        <1> 	mov	eax, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4004 00001F5C 50                  <1> 	push	eax
  4005 00001F5D B407                <1> 	mov	ah, 07h			; RECALIBRATE COMMAND
  4006 00001F5F E83AFFFFFF          <1> 	call	NEC_OUTPUT
  4007 00001F64 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4008 00001F66 88DC                <1> 	mov	ah, bl
  4009 00001F68 E831FFFFFF          <1> 	call	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4010 00001F6D E803000000          <1> 	call	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4011 00001F72 58                  <1> 	pop	eax			; THROW AWAY ERROR
  4012                              <1> RC_BACK:
  4013                              <1> 	;pop	cx
  4014                              <1> 	; 24/12/2021
  4015 00001F73 59                  <1> 	pop	ecx
  4016 00001F74 C3                  <1> 	RETn
  4017                              <1> 
  4018                              <1> ;-------------------------------------------------------------------------------
  4019                              <1> ; CHK_STAT_2
  4020                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4021                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4022                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4023                              <1> ;
  4024                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4025                              <1> ;-------------------------------------------------------------------------------
  4026                              <1> CHK_STAT_2:
  4027                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4028 00001F75 B8[9D1F0000]        <1>         mov	eax, CS_BACK		; LOAD NEC_OUTPUT ERROR ADDRESS
  4029 00001F7A 50                  <1> 	push	eax
  4030 00001F7B E828000000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  4031 00001F80 721A                <1> 	jc	short J34		; IF ERROR, RETURN IT
  4032 00001F82 B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  4033 00001F84 E815FFFFFF          <1> 	call	NEC_OUTPUT
  4034 00001F89 E84A000000          <1> 	call	RESULTS			; READ IN THE RESULTS
  4035 00001F8E 720C                <1> 	jc	short J34
  4036 00001F90 A0[5D650000]        <1> 	mov	al, [NEC_STATUS]	; GET THE FIRST STATUS BYTE
  4037 00001F95 2460                <1> 	and	al, 01100000b		; ISOLATE THE BITS
  4038 00001F97 3C60                <1> 	cmp	al, 01100000b		; TEST FOR CORRECT VALUE
  4039 00001F99 7403                <1> 	jz	short J35		; IF ERROR, GO MARK IT
  4040 00001F9B F8                  <1> 	clc				; GOOD RETURN
  4041                              <1> J34:
  4042 00001F9C 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  4043                              <1> CS_BACK:
  4044 00001F9D C3                  <1> 	retn
  4045                              <1> J35:
  4046 00001F9E 800D[5C650000]40    <1> 	or	byte [DSKETTE_STATUS], BAD_SEEK
  4047 00001FA5 F9                  <1> 	stc				; ERROR RETURN CODE
  4048 00001FA6 EBF4                <1> 	jmp	short J34
  4049                              <1> 
  4050                              <1> ;-------------------------------------------------------------------------------
  4051                              <1> ; WAIT_INT
  4052                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4053                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4054                              <1> ;	IF THE DRIVE IS NOT READY.
  4055                              <1> ;
  4056                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4057                              <1> ;-------------------------------------------------------------------------------
  4058                              <1> 
  4059                              <1> ; 17/12/2014
  4060                              <1> ; 2.5 seconds waiting !
  4061                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4062                              <1> ; amount of time to wait for completion interrupt from NEC.
  4063                              <1> 
  4064                              <1> WAIT_INT:
  4065                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4066 00001FA8 FB                  <1> 	sti				; TURN ON INTERRUPTS, JUST IN CASE
  4067 00001FA9 F8                  <1> 	clc				; CLEAR TIMEOUT INDICATOR
  4068                              <1>        ;mov	bl, 10			; CLEAR THE COUNTERS
  4069                              <1>        ;xor	cx, cx			; FOR 2 SECOND WAIT
  4070                              <1> 
  4071                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4072                              <1> 	;
  4073                              <1> 	;WAIT_FOR_MEM:	
  4074                              <1> 	;	Waits for a bit at a specified memory location pointed
  4075                              <1> 	;	to by ES:[DI] to become set.
  4076                              <1> 	;INPUT:
  4077                              <1> 	;	AH=Mask to test with.
  4078                              <1> 	;	ES:[DI] = memory location to watch.
  4079                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4080                              <1> 	;	     (normally 30 microseconds per period.)
  4081                              <1> 
  4082                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4083                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4084                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4085                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4086                              <1> 	; 27/02/2015
  4087 00001FAA B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4088                              <1> WFMS_CHECK_MEM:
  4089 00001FAF F605[59650000]80    <1> 	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4090 00001FB6 7516                <1>         jnz     short J37
  4091                              <1> WFMS_HI:
  4092 00001FB8 E461                <1> 	in	al, PORT_B  ; 061h	; SYS1, wait for lo to hi
  4093 00001FBA A810                <1> 	test	al, 010h		; transition on memory
  4094 00001FBC 75FA                <1> 	jnz	short WFMS_HI		; refresh.
  4095                              <1> WFMS_LO:
  4096 00001FBE E461                <1> 	in	al, PORT_B		;SYS1
  4097 00001FC0 A810                <1> 	test	al, 010h
  4098 00001FC2 74FA                <1> 	jz	short WFMS_LO
  4099 00001FC4 E2E9                <1>         loop	WFMS_CHECK_MEM
  4100                              <1> ;WFMS_OUTER_LP:
  4101                              <1> ;;	or	bl, bl			; check outer counter
  4102                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4103                              <1> ;	dec	bl
  4104                              <1> ;	jz	short J36A	
  4105                              <1> ;	jmp	short WFMS_CHECK_MEM
  4106                              <1> 
  4107                              <1> 	;17/12/2014
  4108                              <1> 	;16/12/2014
  4109                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4110                              <1> ;J36:
  4111                              <1> ;	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4112                              <1> ;	jnz	short J37
  4113                              <1> 	;16/12/2014
  4114                              <1> 	;loop	J36			; COUNT DOWN WHILE WAITING
  4115                              <1> 	;dec	bl			; SECOND LEVEL COUNTER
  4116                              <1> 	;jnz	short J36
  4117                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4118                              <1> ;	jb	short J36
  4119                              <1> 
  4120                              <1> ;WFMS_TIMEOUT:
  4121                              <1> ;J36A:
  4122 00001FC6 800D[5C650000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4123 00001FCD F9                  <1> 	stc				; ERROR RETURN
  4124                              <1> J37:
  4125 00001FCE 9C                  <1> 	pushf				; SAVE CURRENT CARRY
  4126 00001FCF 8025[59650000]7F    <1> 	and	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4127 00001FD6 9D                  <1> 	popf				; RECOVER CARRY
  4128 00001FD7 C3                  <1> 	retn				; GOOD RETURN CODE
  4129                              <1> 
  4130                              <1> ;-------------------------------------------------------------------------------
  4131                              <1> ; RESULTS
  4132                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4133                              <1> ;	FOLLOWING AN INTERRUPT.
  4134                              <1> ;
  4135                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4136                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4137                              <1> ;-------------------------------------------------------------------------------
  4138                              <1> RESULTS:
  4139                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4140 00001FD8 57                  <1> 	push	edi
  4141 00001FD9 BF[5D650000]        <1> 	mov	edi, NEC_STATUS		; POINTER TO DATA AREA
  4142 00001FDE B307                <1> 	mov	bl, 7			; MAX STATUS BYTES
  4143 00001FE0 66BAF403            <1> 	mov	dx, 03F4h		; STATUS PORT
  4144                              <1> 
  4145                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4146                              <1> 
  4147                              <1> _R10: 
  4148                              <1> 	; 16/12/2014
  4149                              <1> 	; wait for (max) 0.5 seconds
  4150                              <1> 	;mov	bh, 2			; HIGH ORDER COUNTER
  4151                              <1> 	;xor	cx, cx			; COUNTER
  4152                              <1> 
  4153                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4154                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4155                              <1> 	; 27/02/2015
  4156                              <1> 
  4157 00001FE4 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4158                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4159                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4160                              <1> 
  4161                              <1> WFPSR_OUTER_LP:
  4162                              <1> 	;
  4163                              <1> WFPSR_CHECK_PORT:
  4164                              <1> J39:					; WAIT FOR MASTER
  4165 00001FE9 EC                  <1> 	in	al, dx			; GET STATUS
  4166 00001FEA 24C0                <1> 	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4167 00001FEC 3CC0                <1> 	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4168 00001FEE 7418                <1> 	jz	short J42		; STATUS AND DIRECTION OK
  4169                              <1> WFPSR_HI:
  4170 00001FF0 E461                <1> 	in	al, PORT_B	;061h	; SYS1	; wait for hi to lo
  4171 00001FF2 A810                <1> 	test	al, 010h		; transition on memory
  4172 00001FF4 75FA                <1> 	jnz	short WFPSR_HI		; refresh.
  4173                              <1> WFPSR_LO:
  4174 00001FF6 E461                <1> 	in	al, PORT_B		; SYS1
  4175 00001FF8 A810                <1> 	test	al, 010h
  4176 00001FFA 74FA                <1> 	jz	short WFPSR_LO
  4177 00001FFC E2EB                <1>         loop	WFPSR_CHECK_PORT
  4178                              <1> 	
  4179                              <1> 	;; 27/02/2015
  4180                              <1> 	;;dec	bh
  4181                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4182                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4183                              <1> 
  4184                              <1> 	;;mov	byte [wait_count], 0
  4185                              <1> ;J39:					; WAIT FOR MASTER
  4186                              <1> ;	in	al, dx			; GET STATUS
  4187                              <1> ;	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4188                              <1> ;	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4189                              <1> ;	jz	short J42		; STATUS AND DIRECTION OK
  4190                              <1> 	;loop	J39			; LOOP TILL TIMEOUT
  4191                              <1> 	;dec	bh			; DECREMENT HIGH ORDER COUNTER
  4192                              <1> 	;jnz	short J39		; REPEAT TILL DELAY DONE
  4193                              <1> 	;
  4194                              <1> 	;;cmp	byte [wait_count], 10	; (10/18.2 seconds)
  4195                              <1> 	;;jb	short J39	
  4196                              <1> 
  4197                              <1> ;WFPSR_TIMEOUT:
  4198 00001FFE 800D[5C650000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4199 00002005 F9                  <1> 	stc				; SET ERROR RETURN
  4200 00002006 EB29                <1> 	jmp	short POPRES		; POP REGISTERS AND RETURN
  4201                              <1> 
  4202                              <1> ;-----	READ IN THE STATUS
  4203                              <1> 
  4204                              <1> J42:
  4205 00002008 EB00                <1> 	JMP	$+2			; I/O DELAY
  4206                              <1> 	;inc	dx			; POINT AT DATA PORT
  4207 0000200A FEC2                <1> 	inc	dl
  4208 0000200C EC                  <1> 	in	al, dx			; GET THE DATA
  4209                              <1> 	; 16/12/2014
  4210                              <1> 	NEWIODELAY
  2165 0000200D E6EB                <2>  out 0EBh,al
  4211 0000200F 8807                <1>         mov	[edi], al		; STORE THE BYTE
  4212 00002011 47                  <1> 	inc	edi			; INCREMENT THE POINTER
  4213                              <1> 	; 16/12/2014
  4214                              <1> ;	push	cx
  4215                              <1> ;	mov	cx, 30
  4216                              <1> ;wdw2:
  4217                              <1> ;	NEWIODELAY
  4218                              <1> ;	loop	wdw2
  4219                              <1> ;	pop	cx
  4220                              <1> 
  4221 00002012 B903000000          <1> 	mov	ecx,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4222 00002017 E89CF4FFFF          <1> 	call	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4223                              <1> 	;dec	dx			; POINT AT STATUS PORT
  4224 0000201C FECA                <1> 	dec	dl
  4225 0000201E EC                  <1> 	in	al, dx			; GET STATUS
  4226                              <1> 	; 16/12/2014
  4227                              <1> 	NEWIODELAY
  2165 0000201F E6EB                <2>  out 0EBh,al
  4228                              <1> 	;
  4229 00002021 A810                <1> 	test	al, 00010000b		; TEST FOR NEC STILL BUSY
  4230 00002023 740C                <1> 	jz	short POPRES		; RESULTS DONE ?
  4231                              <1> 
  4232 00002025 FECB                <1> 	dec	bl			; DECREMENT THE STATUS COUNTER
  4233 00002027 75BB                <1>         jnz	short _R10              ; GO BACK FOR MORE
  4234 00002029 800D[5C650000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES
  4235 00002030 F9                  <1> 	stc				; SET ERROR FLAG
  4236                              <1> 
  4237                              <1> ;-----	RESULT OPERATION IS DONE
  4238                              <1> POPRES:
  4239 00002031 5F                  <1> 	pop	edi
  4240 00002032 C3                  <1> 	retn				; RETURN WITH CARRY SET
  4241                              <1> 
  4242                              <1> ;-------------------------------------------------------------------------------
  4243                              <1> ; READ_DSKCHNG
  4244                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  4245                              <1> ;
  4246                              <1> ; ON ENTRY:	EDI = DRIVE #
  4247                              <1> ;
  4248                              <1> ; ON EXIT:	EDI = DRIVE #
  4249                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  4250                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  4251                              <1> ;		EAX, ECX, EDX DESTROYED
  4252                              <1> ;-------------------------------------------------------------------------------
  4253                              <1> READ_DSKCHNG:
  4254                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4255 00002033 E8ABFDFFFF          <1> 	call	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  4256 00002038 66BAF703            <1> 	mov	dx, 03F7h		; ADDRESS DIGITAL INPUT REGISTER
  4257 0000203C EC                  <1> 	in	al, dx			; INPUT DIGITAL INPUT REGISTER
  4258 0000203D A880                <1> 	test	al, DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  4259 0000203F C3                  <1> 	retn				; RETURN TO CALLER WITH ZERO FLAG SET
  4260                              <1> 
  4261                              <1> fdc_int:  
  4262                              <1> 	  ; 30/07/2015	
  4263                              <1> 	  ; 16/02/2015
  4264                              <1> ;int_0Eh: ; 11/12/2014
  4265                              <1> 
  4266                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  4267                              <1> ; DISK_INT
  4268                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  4269                              <1> ;
  4270                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  4271                              <1> ;-------------------------------------------------------------------------------
  4272                              <1> DISK_INT_1:
  4273                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4274                              <1> 	;push	eax			; SAVE WORK REGISTER
  4275                              <1> 	; 24/12/2021
  4276 00002040 50                  <1> 	push	eax
  4277 00002041 1E                  <1> 	push	ds
  4278 00002042 66B81000            <1> 	mov	ax, KDATA
  4279 00002046 8ED8                <1> 	mov 	ds, ax
  4280 00002048 800D[59650000]80    <1>         or	byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  4281 0000204F B020                <1> 	mov	al, EOI			; END OF INTERRUPT MARKER
  4282 00002051 E620                <1> 	out	INTA00, al		; INTERRUPT CONTROL PORT
  4283 00002053 1F                  <1> 	pop	ds
  4284                              <1> 	;pop	ax			; RECOVER REGISTER
  4285                              <1> 	; 24/12/2021
  4286 00002054 58                  <1> 	pop	eax
  4287 00002055 CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  4288                              <1> 
  4289                              <1> ;-------------------------------------------------------------------------------
  4290                              <1> ; DSKETTE_SETUP
  4291                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  4292                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  4293                              <1> ;-------------------------------------------------------------------------------
  4294                              <1> DSKETTE_SETUP:
  4295                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4296                              <1> 	;push	eax			; SAVE REGISTERS
  4297                              <1> 	;push	ebx
  4298                              <1> 	;push	ecx
  4299 00002056 52                  <1> 	push	edx
  4300                              <1> 	;push	edi
  4301                              <1> 	; 14/12/2014
  4302                              <1> 	;mov	dword [DISK_POINTER], MD_TBL6
  4303                              <1> 	;
  4304                              <1> 	;or	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  4305                              <1> 
  4306 00002057 31FF                <1> 	xor	edi, edi 		; INITIALIZE DRIVE POINTER
  4307 00002059 29C9                <1> 	sub	ecx, ecx
  4308 0000205B 66890D[67650000]    <1> 	mov	[DSK_STATE], cx ; 0	; INITIALIZE STATES
  4309                              <1> 	; 08/07/2022
  4310                              <1> 	;and	byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  4311 00002062 800D[64650000]C0    <1> 	or	byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  4312 00002069 880D[59650000]      <1> 	mov	[SEEK_STATUS], cl ; 0	; INDICATE RECALIBRATE NEEDED
  4313 0000206F 880D[5B650000]      <1> 	mov	[MOTOR_COUNT], cl ; 0	; INITIALIZE MOTOR COUNT
  4314 00002075 880D[5A650000]      <1> 	mov	[MOTOR_STATUS], cl ; 0	; INITIALIZE DRIVES TO OFF STATE
  4315 0000207B 880D[5C650000]      <1> 	mov	[DSKETTE_STATUS], cl ; 0 ; NO ERRORS
  4316                              <1> 	;
  4317                              <1> 	; 28/02/2015
  4318                              <1> 	;mov	word [cfd], 100h 
  4319 00002081 E850F8FFFF          <1> 	call	DSK_RESET
  4320 00002086 5A                  <1> 	pop	edx
  4321 00002087 C3                  <1> 	retn
  4322                              <1> 
  4323                              <1> ;//////////////////////////////////////////////////////
  4324                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4325                              <1> ;
  4326                              <1> 
  4327                              <1> int13h: ; 21/02/2015
  4328 00002088 9C                  <1> 	pushfd
  4329 00002089 0E                  <1> 	push 	cs
  4330 0000208A E858000000          <1> 	call 	DISK_IO
  4331 0000208F C3                  <1> 	retn
  4332                              <1> 
  4333                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  4334                              <1> ;/////////////////////////////////////////////////////////////////////
  4335                              <1> 
  4336                              <1> ; 10/07/2022
  4337                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4338                              <1> 
  4339                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  4340                              <1> ; 23/02/2015
  4341                              <1> ; 21/02/2015 (unix386.s)
  4342                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  4343                              <1> ;
  4344                              <1> ; Original Source Code:
  4345                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  4346                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  4347                              <1> ;
  4348                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  4349                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  4350                              <1> ;
  4351                              <1> 
  4352                              <1> ;The wait for controller to be not busy is 10 seconds.
  4353                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4354                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  4355                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  4356                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  4357                              <1> 
  4358                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  4359                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4360                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  4361                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  4362                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  4363                              <1> 
  4364                              <1> ;The wait for Data request on read and write longs is
  4365                              <1> ;2000 us. (?)
  4366                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  4367                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  4368                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  4369                              <1> 
  4370                              <1> ; Port 61h (PORT_B)
  4371                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  4372                              <1> 
  4373                              <1> ; 23/12/2014
  4374                              <1> %define CMD_BLOCK       ebp-8  ; 21/02/2015
  4375                              <1> 
  4376                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4377                              <1> 
  4378                              <1> ;--- INT 13H -------------------------------------------------------------------
  4379                              <1> ;									       :
  4380                              <1> ; FIXED DISK I/O INTERFACE						       :
  4381                              <1> ;									       :
  4382                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  4383                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  4384                              <1> ;									       :
  4385                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  4386                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  4387                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  4388                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  4389                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  4390                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  4391                              <1> ;									       :
  4392                              <1> ;------------------------------------------------------------------------------:
  4393                              <1> ;									       :
  4394                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  4395                              <1> ;									       :
  4396                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  4397                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY -chs-                  :
  4398                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY -chs-		       :
  4399                              <1> ;	(AH)= 03H  READ THE DESIRED SECTORS INTO MEMORY -lba-                  :
  4400                              <1> ;	(AH)= 04H  WRITE THE DESIRED SECTORS FROM MEMORY -lba-		       :
  4401                              <1> ;	(AH)= 05H  ALTERNATE DISK RESET (SEE DL)			       :
  4402                              <1> ;                                                                              :
  4403                              <1> ;------------------------------------------------------------------------------:
  4404                              <1> ;									       :
  4405                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  4406                              <1> ;									       :
  4407                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  4408                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  4409                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  4410                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  4411                              <1> ;									       :
  4412                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  4413                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  4414                              <1> ;				 (10 BITS TOTAL)			       :
  4415                              <1> ;									       :
  4416                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  4417                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  4418                              <1> ;									       :
  4419                              <1> ;		(EBX)   -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  4420                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  4421                              <1> ;									       :
  4422                              <1> ;------------------------------------------------------------------------------:
  4423                              <1> ; OUTPUT								       :
  4424                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  4425                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  4426                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  4427                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  4428                              <1> ;									       :
  4429                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  4430                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  4431                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  4432                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  4433                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  4434                              <1> ;		REWRITTEN.						       :
  4435                              <1> ;									       :
  4436                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  4437                              <1> ;	   INPUT:							       :
  4438                              <1> ;	     (DL) = DRIVE NUMBER					       :
  4439                              <1> ;	   OUTPUT:							       :
  4440                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  4441                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  4442                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  4443                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  4444                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  4445                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  4446                              <1> ;									       :
  4447                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  4448                              <1> ;	INFORMATION.							       :
  4449                              <1> ;									       :
  4450                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  4451                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  4452                              <1> ;									       :
  4453                              <1> ;-------------------------------------------------------------------------------
  4454                              <1> 
  4455                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  4456                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  4457                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  4458                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  4459                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  4460                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  4461                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  4462                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  4463                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  4464                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  4465                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  4466                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  4467                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  4468                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  4469                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  4470                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  4471                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  4472                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  4473                              <1> 
  4474                              <1> ;--------------------------------------------------------
  4475                              <1> ;							:
  4476                              <1> ; FIXED DISK PARAMETER TABLE				:
  4477                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  4478                              <1> ;							:
  4479                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  4480                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  4481                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  4482                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  4483                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  4484                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  4485                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  4486                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  4487                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  4488                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  4489                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  4490                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  4491                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  4492                              <1> ;							:
  4493                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  4494                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  4495                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  4496                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  4497                              <1> ;							:
  4498                              <1> ;--------------------------------------------------------
  4499                              <1> 
  4500                              <1> ;--------------------------------------------------------
  4501                              <1> ;							:
  4502                              <1> ; HARDWARE SPECIFIC VALUES				:
  4503                              <1> ;							:
  4504                              <1> ;  -  CONTROLLER I/O PORT				:
  4505                              <1> ;							:
  4506                              <1> ;     > WHEN READ FROM: 				:
  4507                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  4508                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  4509                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  4510                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  4511                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  4512                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  4513                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  4514                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  4515                              <1> ;							:
  4516                              <1> ;     > WHEN WRITTEN TO:				:
  4517                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  4518                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  4519                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  4520                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  4521                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  4522                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  4523                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  4524                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  4525                              <1> ;							:
  4526                              <1> ;--------------------------------------------------------
  4527                              <1> 
  4528                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  4529                              <1> ;HF1_PORT	equ	0170h	
  4530                              <1> ;HF_REG_PORT	EQU	03F6H
  4531                              <1> ;HF1_REG_PORT	equ	0376h
  4532                              <1> 
  4533                              <1> HDC1_BASEPORT	equ	1F0h
  4534                              <1> HDC2_BASEPORT	equ	170h		
  4535                              <1> 
  4536                              <1> align 2
  4537                              <1> 
  4538                              <1> ;-----		STATUS REGISTER
  4539                              <1> 
  4540                              <1> ST_ERROR	EQU	00000001B	;
  4541                              <1> ST_INDEX	EQU	00000010B	;
  4542                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  4543                              <1> ST_DRQ		EQU	00001000B	;
  4544                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  4545                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  4546                              <1> ST_READY	EQU	01000000B	;
  4547                              <1> ST_BUSY 	EQU	10000000B	;
  4548                              <1> 
  4549                              <1> ;-----		ERROR REGISTER
  4550                              <1> 
  4551                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  4552                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  4553                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  4554                              <1> ;		EQU	00001000B	; NOT USED
  4555                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  4556                              <1> ;		EQU	00100000B	; NOT USED
  4557                              <1> ERR_DATA_ECC	EQU	01000000B
  4558                              <1> ERR_BAD_BLOCK	EQU	10000000B
  4559                              <1> 
  4560                              <1> 
  4561                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  4562                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  4563                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  4564                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  4565                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  4566                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  4567                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  4568                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  4569                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  4570                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  4571                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  4572                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  4573                              <1> 
  4574                              <1> ;MAX_FILE	EQU	2
  4575                              <1> ;S_MAX_FILE	EQU	2
  4576                              <1> MAX_FILE	equ	4		; 22/12/2014
  4577                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  4578                              <1> 
  4579                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  4580                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  4581                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  4582                              <1> 
  4583                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  4584                              <1> 
  4585                              <1> ;-----		COMMAND BLOCK REFERENCE
  4586                              <1> 
  4587                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  4588                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  4589                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  4590                              <1> ; 19/12/2014
  4591                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  4592                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  4593                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4594                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4595                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  4596                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  4597                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  4598                              <1> 
  4599                              <1> align 2
  4600                              <1> 
  4601                              <1> ;----------------------------------------------------------------
  4602                              <1> ; FIXED DISK I/O SETUP						:
  4603                              <1> ;								:
  4604                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  4605                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  4606                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  4607                              <1> ;								:
  4608                              <1> ;----------------------------------------------------------------
  4609                              <1> 
  4610                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4611                              <1> 
  4612                              <1> DISK_SETUP:
  4613                              <1> 	;CLI
  4614                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  4615                              <1> 	;xor	ax,ax
  4616                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  4617                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  4618                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  4619                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  4620                              <1> 	;MOV	[DISK_VECTOR+2],AX
  4621                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  4622                              <1> 	;MOV	[ORG_VECTOR+2],CS
  4623                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  4624                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  4625                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  4626                              <1> 	;;MOV	[HDISK_INT+2],CS
  4627                              <1> 	;mov	[HDISK_INT1+2],CS
  4628                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  4629                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  4630                              <1> 	;mov	[HDISK_INT2+2],CS
  4631                              <1> 	;
  4632                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  4633                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  4634                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  4635                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  4636                              <1> 	;push	cs
  4637                              <1> 	;pop	ds
  4638                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  4639                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  4640 00002090 C705[70650000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  4640 00002098 0900                <1>
  4641                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  4642                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  4643 0000209A C705[74650000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  4643 000020A2 0900                <1>
  4644                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  4645                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  4646 000020A4 C705[78650000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  4646 000020AC 0900                <1>
  4647                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  4648                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  4649 000020AE C705[7C650000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  4649 000020B6 0900                <1>
  4650                              <1> 	;
  4651                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  4652                              <1> 	;;;AND	AL,0BFH
  4653                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  4654                              <1> 	;;;JMP	$+2
  4655                              <1> 	;;IODELAY
  4656                              <1> 	;;OUT	INTB01,AL
  4657                              <1> 	;;IODELAY
  4658                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  4659                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  4660                              <1> 	;;;JMP	$+2
  4661                              <1> 	;;IODELAY
  4662                              <1> 	;;OUT	INTA01,AL
  4663                              <1> 	;
  4664                              <1> 	;STI
  4665                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  4666                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  4667                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  4668                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  4669                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  4670                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  4671                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  4672                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  4673                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  4674                              <1> 	;mov	si, hd0_type
  4675 000020B8 BE[D05F0000]        <1> 	mov	esi, hd0_type
  4676                              <1> 	;mov	cx, 4
  4677 000020BD B904000000          <1> 	mov	ecx, 4
  4678                              <1> hde_l:
  4679 000020C2 AC                  <1> 	lodsb
  4680 000020C3 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  4681 000020C5 7206                <1> 	jb	short _L4
  4682 000020C7 FE05[6C650000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  4683                              <1> _L4: ; 26/02/2015
  4684 000020CD E2F3                <1> 	loop	hde_l	
  4685                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  4686                              <1> ;L4:
  4687                              <1> 	; 
  4688                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  4689                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  4690                              <1> 	;;mov 	cl, 3
  4691                              <1> 	;;
  4692                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  4693                              <1> ;;hdc_dl:
  4694                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  4695                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  4696                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  4697                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  4698                              <1> 	;;jnc	short hdc_reset0
  4699                              <1> 	;;loop	hdc_dl
  4700                              <1> 	;;; 27/12/2014
  4701                              <1> 	;;stc
  4702                              <1> 	;;retn
  4703                              <1> 	;
  4704                              <1> ;;hdc_reset0:
  4705                              <1> 	; 18/01/2015
  4706 000020CF 8A0D[6C650000]      <1> 	mov	cl, [HF_NUM]
  4707 000020D5 20C9                <1> 	and	cl, cl
  4708 000020D7 740D                <1> 	jz	short POD_DONE
  4709                              <1> 	;
  4710 000020D9 B27F                <1> 	mov	dl, 7Fh
  4711                              <1> hdc_reset1:
  4712 000020DB FEC2                <1> 	inc	dl
  4713                              <1> 	;; 31/12/2015
  4714                              <1> 	;;push	dx
  4715                              <1> 	;;push	cx
  4716                              <1> 	;;push	ds
  4717                              <1> 	;;sub	ax, ax
  4718                              <1> 	;;mov	ds, ax
  4719                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  4720                              <1> 	;;pop	ds
  4721                              <1> 	;;MOV	BX,AX
  4722                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  4723                              <1> 	;;MOV	CX,AX
  4724                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  4725                              <1> 	;;
  4726                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  4727                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  4728                              <1> 	;;pop	cx
  4729                              <1> 	;;pop	dx
  4730                              <1> 	;;
  4731                              <1> 	; 18/01/2015
  4732                              <1> 	;mov	ah, 0Dh ; ALTERNATE RESET
  4733                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4734 000020DD B405                <1> 	mov	ah, 5 ; ALTERNATE RESET
  4735                              <1> 	;int	13h
  4736 000020DF E8A4FFFFFF          <1> 	call	int13h
  4737 000020E4 E2F5                <1> 	loop	hdc_reset1
  4738                              <1> POD_DONE:
  4739 000020E6 C3                  <1> 	RETn
  4740                              <1> 
  4741                              <1> ;----------------------------------------
  4742                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  4743                              <1> ;----------------------------------------
  4744                              <1> 
  4745                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4746                              <1> 
  4747                              <1> DISK_IO:
  4748 000020E7 80FA80              <1> 	cmp	dl, 80h			; TEST FOR FIXED DISK DRIVE
  4749                              <1> 	;jae	short A1		; YES, HANDLE HERE
  4750                              <1> 	;;;int	40H			; DISKETTE HANDLER
  4751                              <1> 	;;call	int40h
  4752                              <1> 	;jb	DISKETTE_IO_1
  4753                              <1> 	; 24/12/2021
  4754 000020EA 7305                <1> 	jnb	short A1
  4755 000020EC E96BF6FFFF          <1> 	jmp	DISKETTE_IO_1
  4756                              <1> ;RET_2:
  4757                              <1> ;	retf	4			; BACK TO CALLER
  4758                              <1> A1:
  4759 000020F1 FB                  <1> 	sti				; ENABLE INTERRUPTS
  4760 000020F2 80FA83              <1> 	cmp	dl, (80h + S_MAX_FILE - 1)
  4761 000020F5 7712                <1> 	ja	short RET_2
  4762                              <1> 	; 18/01/2015
  4763 000020F7 08E4                <1> 	or	ah, ah
  4764 000020F9 7413                <1> 	jz	short A3 ; 08/07/2022
  4765 000020FB 80FC05              <1> 	cmp	ah, 5  ; Alternate reset
  4766 000020FE 740C                <1> 	je	short A2
  4767                              <1> 	;cmp	ah, M1L/4 ; cmp ah, 6
  4768 00002100 720C                <1> 	jb	short A3
  4769                              <1> 	; BAD COMMAND
  4770 00002102 C605[6B650000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  4771                              <1> RET_2:
  4772 00002109 CA0400              <1> 	retf	4
  4773                              <1> A2:
  4774 0000210C 28E4                <1> 	sub	ah, ah	; Reset
  4775                              <1> A3:
  4776                              <1> 					; SAVE REGISTERS DURING OPERATION
  4777 0000210E C8080000            <1> 	enter	8,0			; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK
  4778                              <1> 	; 08/07/2022
  4779 00002112 53                  <1> 	push	ebx			;  IN THE STACK, THE COMMAND BLOCK IS:
  4780 00002113 51                  <1> 	push	ecx			;   @CMD_BLOCK == BYTE PTR [EBP]-8
  4781 00002114 52                  <1> 	push	edx
  4782 00002115 56                  <1> 	push	esi
  4783 00002116 57                  <1> 	push	edi
  4784 00002117 E827000000          <1> 	call	DISK_IO_CONT		; PERFORM THE OPERATION
  4785 0000211C 8A25[6B650000]      <1> 	mov	ah, [DISK_STATUS1]	; GET STATUS FROM OPERATION
  4786 00002122 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  4787 00002125 F5                  <1> 	cmc				; SUCCESS OR FAILURE
  4788 00002126 5F                  <1> 	pop	edi			; RESTORE REGISTERS
  4789 00002127 5E                  <1> 	pop	esi
  4790 00002128 5A                  <1>       	pop	edx
  4791 00002129 59                  <1> 	pop	ecx
  4792 0000212A 5B                  <1> 	pop	ebx
  4793 0000212B C9                  <1> 	leave				; ADJUST (ESP) AND RESTORE (EBP)
  4794 0000212C CA0400              <1> 	retf	4			; THROW AWAY SAVED FLAGS
  4795                              <1> 
  4796                              <1> ; 21/02/2015
  4797                              <1> ;       dw --> dd
  4798                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4799                              <1> M1:					; FUNCTION TRANSFER TABLE
  4800 0000212F [74220000]          <1> 	dd	DISK_RESET		; 00h
  4801 00002133 [E7220000]          <1> 	dd	DISK_READ		; 01h
  4802 00002137 [20230000]          <1> 	dd	DISK_WRITE		; 02h
  4803 0000213B [E7220000]          <1> 	dd	DISK_READ		; 03h ; LBA read
  4804 0000213F [20230000]          <1> 	dd	DISK_WRITE		; 04h ; LBA write
  4805                              <1> 	;dd	DISK_RESET		; 05h
  4806                              <1> 
  4807                              <1> M1L     EQU    $-M1
  4808                              <1> 
  4809                              <1> DISK_IO_CONT:
  4810                              <1> 	; 10/07/2022
  4811                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4812                              <1> SU0:
  4813 00002143 C605[6B650000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; RESET THE STATUS INDICATOR
  4814                              <1> 	; 10/07/2022
  4815 0000214A 89DE                <1> 	mov	esi, ebx ; 21/02/2015	; DATA (BUFFER) ADDRESS
  4816 0000214C 8A1D[6C650000]      <1> 	mov	bl, [HF_NUM]		; GET NUMBER OF DRIVES
  4817 00002152 80E27F              <1> 	and	dl, 7Fh			; GET DRIVE AS 0 OR 1
  4818                              <1> 					; (get drive number as 0 to 3)
  4819 00002155 38D3                <1> 	cmp	bl, dl
  4820                              <1>         ;;jbe	BAD_COMMAND_POP         ; INVALID DRIVE
  4821                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  4822                              <1> 	; 24/12/2021
  4823 00002157 7705                <1> 	ja	short su0_su1
  4824 00002159 E90C010000          <1> 	jmp	BAD_COMMAND
  4825                              <1> su0_su1:
  4826                              <1>         ;;03/01/2015
  4827 0000215E 29DB                <1> 	sub	ebx, ebx
  4828 00002160 88D3                <1> 	mov	bl, dl
  4829 00002162 883D[80650000]      <1> 	mov	[LBAMode], bh  ; 0
  4830                              <1> 	;test	byte [ebx+hd0_type], 1	; LBA ready ?
  4831                              <1> 	;jz	short su1		; no
  4832                              <1> 	;inc	byte [LBAMode]
  4833                              <1> ;su1:
  4834                              <1> 	; 21/02/2015 (32 bit modification)
  4835                              <1> 	; 04/01/2015
  4836                              <1> 	;push	ax ; ***
  4837                              <1> 	; 24/12/2021
  4838 00002168 50                  <1> 	push	eax ; ***
  4839                              <1> 	; 24/12/2021
  4840 00002169 52                  <1> 	push	edx ; *
  4841 0000216A 50                  <1> 	push	eax
  4842 0000216B E83A040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  4843                              <1> 	; 02/02/2015
  4844 00002170 668B4310            <1> 	mov	ax, [ebx+16]   ; I/O port base address (1F0h, 170h)
  4845 00002174 66A3[C45F0000]      <1> 	mov	[HF_PORT], ax
  4846 0000217A 668B5312            <1> 	mov	dx, [ebx+18]   ; control port address (3F6h, 376h)
  4847 0000217E 668915[C65F0000]    <1> 	mov	[HF_REG_PORT], dx
  4848 00002185 8A4314              <1> 	mov	al, [ebx+20]   ; head register upper nibble (A0h,B0h,E0h,F0h)
  4849                              <1> 	; 23/02/2015
  4850 00002188 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  4851 0000218A 7406                <1> 	jz 	short su1
  4852 0000218C FE05[80650000]      <1> 	inc	byte [LBAMode] ; 1 
  4853                              <1> su1: 	 
  4854 00002192 C0E804              <1> 	shr 	al, 4
  4855 00002195 2401                <1> 	and	al, 1			
  4856 00002197 A2[C85F0000]        <1> 	mov	[hf_m_s], al 
  4857                              <1> 	;
  4858                              <1> 	; 03/01/2015
  4859 0000219C 8A4308              <1> 	mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  4860                              <1> 	;mov	dx, [HF_REG_PORT]	; Device Control register	
  4861 0000219F EE                  <1> 	out	dx, al			; SET EXTRA HEAD OPTION
  4862                              <1> 					; Control Byte: (= 08h, here)
  4863                              <1> 					; bit 0 - 0
  4864                              <1> 					; bit 1 - nIEN (1 = disable irq)
  4865                              <1> 					; bit 2 - SRST (software RESET)
  4866                              <1> 					; bit 3 - use extra heads (8 to 15)
  4867                              <1> 					;         -always set to 1-	
  4868                              <1> 					; (bits 3 to 7 are reserved
  4869                              <1> 					;          for ATA devices)
  4870 000021A0 8A25[6D650000]      <1> 	mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  4871 000021A6 80E4C0              <1> 	and	ah, 0C0h 		; CONTROL BYTE
  4872 000021A9 08C4                <1> 	or	ah, al
  4873 000021AB 8825[6D650000]      <1> 	mov	[CONTROL_BYTE], ah	
  4874                              <1> 	; 04/01/2015
  4875                              <1> 	;pop	ax
  4876                              <1> 	; 24/12/2021
  4877 000021B1 58                  <1> 	pop	eax
  4878                              <1> 	;pop	dx ; * ;; 14/02/2015
  4879                              <1> 	; 24/12/2021
  4880 000021B2 5A                  <1> 	pop	edx ; *
  4881 000021B3 20E4                <1> 	and	ah, ah	; Reset function ?
  4882 000021B5 7506                <1> 	jnz	short su2
  4883                              <1> 	;pop	ax ; ***
  4884                              <1> 	; 24/12/2021
  4885 000021B7 58                  <1> 	pop	eax ; ***	
  4886                              <1> 	;;pop	bx
  4887 000021B8 E9B7000000          <1>         jmp     DISK_RESET
  4888                              <1> su2:
  4889 000021BD 803D[80650000]00    <1> 	cmp	byte [LBAMode], 0
  4890 000021C4 7659                <1> 	jna	short su3
  4891                              <1> 	;
  4892                              <1> 	; 02/02/2015 (LBA read/write function calls)
  4893                              <1> 	;cmp	ah, 1Bh
  4894 000021C6 80FC03              <1> 	cmp	ah, 3 ; 08/07/2022
  4895 000021C9 7206                <1> 	jb	short lbarw1
  4896                              <1> 	;;cmp	ah, 1Ch
  4897                              <1> 	;cmp	ah, 4 ; 08/07/2022 
  4898                              <1> 	;ja 	short invldfnc
  4899                              <1> 	;;pop	dx ; * ; 14/02/2015
  4900                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  4901 000021CB 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  4902                              <1> 	;; 14/02/2015
  4903 000021CD 88D1                <1> 	mov	cl, dl ; 14/02/2015
  4904                              <1> 	;;mov	dx, bx
  4905                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  4906                              <1> 	;;mov	bx, di
  4907                              <1> 	;mov	si, di ; Buffer offset
  4908 000021CF EB2E                <1> 	jmp	short lbarw2
  4909                              <1> lbarw1:
  4910                              <1> 	; convert CHS to LBA
  4911                              <1> 	;
  4912                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  4913                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  4914                              <1> 	;	+ Sector - 1
  4915                              <1> 	;push	dx ; * ;; 14/02/2015
  4916                              <1> 	; 24/12/2021
  4917 000021D1 52                  <1> 	push	edx ; *
  4918                              <1> 	;xor	dh, dh
  4919 000021D2 31D2                <1> 	xor	edx, edx
  4920 000021D4 8A530E              <1> 	mov	dl, [ebx+14]	; sectors per track (logical)
  4921                              <1> 	;xor	ah, ah
  4922 000021D7 31C0                <1> 	xor	eax, eax
  4923 000021D9 8A4302              <1> 	mov	al, [ebx+2]	; heads (logical) 
  4924 000021DC FEC8                <1> 	dec	al
  4925                              <1> 	;inc	ax		; 0 =  256
  4926 000021DE 40                  <1> 	inc	eax ; 24/12/2021
  4927 000021DF 66F7E2              <1> 	mul 	dx
  4928                              <1> 		; AX = # of Heads * Sectors/Track
  4929 000021E2 6689CA              <1> 	mov	dx, cx
  4930                              <1> 	;and	cx, 3Fh	 ; sector (1 to 63)
  4931 000021E5 83E13F              <1> 	and	ecx, 3fh
  4932 000021E8 86D6                <1> 	xchg	dl, dh
  4933 000021EA C0EE06              <1> 	shr	dh, 6
  4934                              <1> 		; DX = cylinder (0 to 1023)
  4935                              <1> 	;mul 	dx
  4936                              <1> 		; DX:AX = # of Heads * Sectors/Track * Cylinder
  4937 000021ED F7E2                <1> 	mul	edx
  4938 000021EF FEC9                <1> 	dec	cl  ; sector - 1
  4939                              <1> 	;add	ax, cx
  4940                              <1> 	;adc	dx, 0
  4941                              <1> 		; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1
  4942 000021F1 01C8                <1> 	add	eax, ecx
  4943                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  4944                              <1> 	; 24/12/2021
  4945 000021F3 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  4946                              <1> 	;push	dx
  4947                              <1> 	;push	ax
  4948 000021F4 50                  <1> 	push	eax
  4949 000021F5 8A430E              <1> 	mov	al, [ebx+14]  ; sectors per track (logical)	
  4950 000021F8 F6E5                <1> 	mul	ch
  4951                              <1> 		; AX = Head * Sectors/Track
  4952 000021FA 6699                <1>         cwd
  4953                              <1> 	;pop	dx
  4954 000021FC 5A                  <1> 	pop	edx
  4955                              <1> 	;add	ax, dx
  4956                              <1> 	;pop	dx
  4957                              <1> 	;adc	dx, 0 ; add carry bit
  4958 000021FD 01D0                <1> 	add	eax, edx
  4959                              <1> lbarw2:
  4960 000021FF 29D2                <1> 	sub	edx, edx ; 21/02/2015
  4961 00002201 88CA                <1> 	mov	dl, cl ; 21/02/2015
  4962 00002203 C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  4963                              <1> 				; NOTE: Features register (1F1h, 171h)
  4964                              <1> 				; is not used for ATA device R/W functions. 
  4965                              <1> 				; It is old/obsolete 'write precompensation'
  4966                              <1> 				; register and error register
  4967                              <1> 				; for old ATA/IDE devices.
  4968                              <1> 	; 18/01/2014
  4969                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  4970 00002207 8A0D[C85F0000]      <1> 	mov	cl, [hf_m_s]
  4971                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  4972                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  4973                              <1> 				; bit 6 = 1 = LBA mode
  4974                              <1> 				; bit 7 = 1
  4975 0000220D 80C90E              <1> 	or	cl, 0Eh ; 1110b
  4976                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  4977 00002210 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  4978 00002215 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  4979                              <1> 	;or	dh, ch
  4980 00002218 09C8                <1> 	or	eax, ecx	
  4981                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  4982                              <1> 				  ; (Sector Number Register)
  4983                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  4984                              <1> 				  ; (Cylinder Low Register)
  4985                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  4986                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  4987                              <1> 				  ; (Cylinder High Register)
  4988                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  4989                              <1> 				  ; (Drive/Head Register)
  4990                              <1> 	
  4991                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  4992 0000221A 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  4993                              <1> 	;14/02/2015
  4994                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  4995 0000221D EB37                <1> 	jmp	short su4
  4996                              <1> su3:
  4997                              <1> 	; 02/02/2015 
  4998                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  4999                              <1> 	;cmp 	ah, 14h
  5000                              <1> 	;jna 	short chsfnc
  5001                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5002 0000221F 80FC02              <1> 	cmp	ah, 2
  5003 00002222 7603                <1> 	jna	short chsfnc
  5004                              <1> invldfnc:
  5005                              <1>         ; 14/02/2015  
  5006                              <1> 	;pop	es ; **
  5007                              <1>         ;pop	ax ; ***
  5008                              <1>         ; 24/12/2021
  5009 00002224 58                  <1> 	pop	eax ; ***
  5010                              <1> 	;jmp	short BAD_COMMAND_POP
  5011 00002225 EB43                <1>         jmp     short BAD_COMMAND
  5012                              <1> chsfnc:	
  5013 00002227 668B4305            <1> 	mov	ax, [ebx+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  5014 0000222B 66C1E802            <1> 	shr	ax, 2
  5015 0000222F 8845F8              <1> 	mov	[CMD_BLOCK], al
  5016                              <1> 	;
  5017                              <1> 	;;mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5018                              <1> 	;;push	edx ; *
  5019                              <1> 	;;mov	dx, [HF_REG_PORT]
  5020                              <1> 	;;out	dx, al			; SET EXTRA HEAD OPTION
  5021                              <1> 	;;pop	edx ; * 
  5022                              <1> 	;;mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5023                              <1> 	;;and	ah, 0C0h 		; CONTROL BYTE	
  5024                              <1> 	;;or	ah, al
  5025                              <1> 	;;mov	[CONTROL_BYTE], ah
  5026                              <1> 	;
  5027 00002232 88C8                <1> 	mov	al, cl			; GET SECTOR NUMBER
  5028 00002234 243F                <1> 	and	AL, 3Fh
  5029 00002236 8845FA              <1> 	mov	[CMD_BLOCK+2], al
  5030 00002239 886DFB              <1> 	mov	[CMD_BLOCK+3], ch 	; GET CYLINDER NUMBER
  5031 0000223C 88C8                <1> 	mov	al, cl
  5032 0000223E C0E806              <1> 	shr	al, 6
  5033 00002241 8845FC              <1> 	mov	[CMD_BLOCK+4], al	; CYLINDER HIGH ORDER 2 BITS
  5034                              <1> 	;;05/01/2015
  5035                              <1> 	;;mov	al, dl			; DRIVE NUMBER
  5036 00002244 A0[C85F0000]        <1> 	mov	al, [hf_m_s]
  5037 00002249 C0E004              <1> 	shl	al, 4
  5038 0000224C 80E60F              <1> 	and	DH, 0Fh			; HEAD NUMBER
  5039 0000224F 08F0                <1> 	or	al, dh
  5040 00002251 0CA0                <1> 	or	al, 80h+20h		; ECC AND 512 BYTE SECTORS
  5041 00002253 8845FD              <1> 	mov	[CMD_BLOCK+5], al	; ECC/SIZE/DRIVE/HEAD
  5042                              <1> su4:
  5043                              <1> 	;; 14/02/2015
  5044                              <1>         ;;pop	ax
  5045                              <1>         ;;mov	[CMD_BLOCK+1], AL	; SECTOR COUNT
  5046                              <1>         ;;push	ax
  5047                              <1>         ;;mov	al, ah			; GET INTO LOW BYTE
  5048                              <1>         ;;xor	ah, ah			; ZERO HIGH BYTE
  5049                              <1>         ;;sal	ax, 1			; *2 FOR TABLE LOOKUP
  5050                              <1> 	;pop	ax ; ***
  5051                              <1> 	; 24/12/2021
  5052 00002256 58                  <1> 	pop	eax ; ***
  5053 00002257 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  5054 0000225A 29DB                <1>         sub	ebx, ebx
  5055 0000225C 88E3                <1> 	mov     bl, ah
  5056                              <1>         ;xor	bh, bh
  5057                              <1>         ;sal	bx, 1
  5058 0000225E 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  5059                              <1> 	;;mov	si, ax			; PUT INTO SI FOR BRANCH
  5060                              <1>         ;;cmp	ax, M1L			; TEST WITHIN RANGE
  5061                              <1>         ;;jnb	short BAD_COMMAND_POP
  5062                              <1>     	; 08/07/2022
  5063                              <1> 	;cmp	ebx, M1L
  5064                              <1> 	;jnb	short BAD_COMMAND
  5065 00002262 87DE                <1>         xchg	ebx, esi
  5066                              <1> 	;;;pop	ax			; RESTORE AX
  5067                              <1> 	;;;pop	bx			; AND DATA ADDRESS
  5068                              <1> 	
  5069                              <1> 	;;push	cx
  5070                              <1> 	;;push	ax			; ADJUST ES:BX
  5071                              <1> 	;mov	cx, bx			; GET 3 HIGH ORDER NIBBLES OF BX
  5072                              <1> 	;shr	cx, 4
  5073                              <1> 	;mov	ax, es
  5074                              <1> 	;add	ax, cx
  5075                              <1> 	;mov	es, ax
  5076                              <1> 	;and	bx, 000Fh		; ES:BX CHANGED TO ES:000X
  5077                              <1> 	;;pop	ax
  5078                              <1> 	;;pop	cx
  5079 00002264 FFA6[2F210000]      <1> 	jmp	dword [esi+M1]
  5080                              <1> ;;BAD_COMMAND_POP:
  5081                              <1> ;;	pop	ax
  5082                              <1> ;;	pop	bx
  5083                              <1> BAD_COMMAND:
  5084 0000226A C605[6B650000]01    <1>         mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5085                              <1> 	;mov	al, 0
  5086 00002271 28C0                <1> 	sub	al, al ; 0
  5087 00002273 C3                  <1> 	retn
  5088                              <1> 
  5089                              <1> ; 10/07/2022
  5090                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5091                              <1> 
  5092                              <1> ;----------------------------------------
  5093                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  5094                              <1> ;----------------------------------------
  5095                              <1> 
  5096                              <1> ; 18-1-2015 : one controller reset (not other one)
  5097                              <1> 
  5098                              <1> DISK_RESET:
  5099 00002274 FA                  <1> 	cli
  5100 00002275 E4A1                <1> 	in	al, INTB01		; GET THE MASK REGISTER
  5101                              <1> 	;JMP	$+2
  5102                              <1> 	IODELAY
  2160 00002277 EB00                <2>  jmp short $+2
  2161 00002279 EB00                <2>  jmp short $+2
  5103                              <1> 	;and	al, 0BFh 		; ENABLE FIXED DISK INTERRUPT
  5104 0000227B 243F                <1> 	and	al, 3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  5105 0000227D E6A1                <1> 	out	INTB01, al
  5106 0000227F FB                  <1> 	sti				; START INTERRUPTS
  5107                              <1> 	; 14/02/2015
  5108                              <1> 	;mov	di, dx
  5109                              <1> 	; 24/12/2021
  5110 00002280 89D7                <1> 	mov	edi, edx	
  5111                              <1> 	; 04/01/2015
  5112                              <1> 	;xor	di,di
  5113                              <1> drst0:
  5114 00002282 B004                <1> 	mov	al, 04h  ; bit 2 - SRST 
  5115                              <1> 	;mov	dx, HF_REG_PORT
  5116 00002284 668B15[C65F0000]    <1> 	mov	dx, [HF_REG_PORT]
  5117 0000228B EE                  <1> 	out	dx, al			; RESET
  5118                              <1> ;	mov	cx, 10			; DELAY COUNT
  5119                              <1> ;DRD:	dec	cx
  5120                              <1> ;	jnz	short DRD		; WAIT 4.8 MICRO-SEC
  5121                              <1> 	;mov	cx, 2			; wait for 30 micro seconds	
  5122                              <1>         ;mov	ecx, 2 ; 21/02/2015
  5123                              <1> 	; 10/07/2022
  5124 0000228C 29C9                <1> 	sub	ecx, ecx
  5125 0000228E B102                <1> 	mov	cl, 2
  5126 00002290 E823F2FFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  5127                              <1>                                         ; 40 micro seconds)
  5128 00002295 A0[6D650000]        <1> 	mov	al, [CONTROL_BYTE]
  5129 0000229A 240F                <1> 	and	al, 0Fh			; SET HEAD OPTION
  5130 0000229C EE                  <1> 	out	dx, al			; TURN RESET OFF
  5131 0000229D E83E020000          <1> 	call	NOT_BUSY
  5132 000022A2 7514                <1> 	jnz	short DRERR		; TIME OUT ON RESET
  5133 000022A4 668B15[C45F0000]    <1> 	mov	dx, [HF_PORT]
  5134 000022AB FEC2                <1> 	inc	dl  ; HF_PORT+1
  5135                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  5136                              <1>         ;mov	cl, 10
  5137                              <1>         ;mov     ecx, 10 ; 21/02/2015
  5138                              <1> 	; 10/07/2022
  5139                              <1> 	;xor	ecx, ecx
  5140 000022AD B10A                <1> 	mov	cl, 10 
  5141                              <1> drst1:
  5142 000022AF EC                  <1> 	in	al, dx			; GET RESET STATUS
  5143 000022B0 3C01                <1> 	cmp	al, 1
  5144                              <1> 	; 04/01/2015
  5145 000022B2 740C                <1> 	jz	short drst2
  5146                              <1> 	;jnz	short DRERR		; BAD RESET STATUS
  5147                              <1>         	; Drive/Head Register - bit 4
  5148                              <1> 	;loop	drst1
  5149                              <1> 	; 10/07/2022
  5150 000022B4 FEC9                <1> 	dec	cl
  5151 000022B6 75F7                <1> 	jnz	short drst1
  5152                              <1> DRERR:	
  5153 000022B8 C605[6B650000]05    <1> 	mov	byte [DISK_STATUS1], BAD_RESET ; CARD FAILED
  5154 000022BF C3                  <1> 	retn
  5155                              <1> drst2:
  5156                              <1> 	; 14/02/2015
  5157                              <1> 	;mov	dx, di
  5158                              <1> 	; 24/12/2021
  5159 000022C0 89FA                <1> 	mov	edx, edi
  5160                              <1> ;drst3:
  5161                              <1> ;	; 05/01/2015
  5162                              <1> ;	shl 	di, 1
  5163                              <1> ;	; 04/01/2015
  5164                              <1> ;	mov	ax, [di+hd_cports]
  5165                              <1> ;	cmp	ax,[ HF_REG_PORT]
  5166                              <1> ;	je	short drst4
  5167                              <1> ;	mov	[HF_REG_PORT], ax
  5168                              <1> ;	; 03/01/2015
  5169                              <1> ;	mov	ax, [di+hd_ports]
  5170                              <1> ;       mov     [HF_PORT], ax
  5171                              <1> ;	; 05/01/2014
  5172                              <1> ;	shr	di, 1
  5173                              <1> ;	; 04/01/2015
  5174                              <1> ;	jmp	short drst0	; reset other controller
  5175                              <1> ;drst4:
  5176                              <1> ;	; 05/01/2015
  5177                              <1> ;	shr	di, 1
  5178                              <1> ;	mov	al, [di+hd_dregs]
  5179                              <1> ;	and	al, 10h ; bit 4 only
  5180                              <1> ;	shr	al, 4 ; bit 4  -> bit 0
  5181                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  5182                              <1> 	;
  5183 000022C2 A0[C85F0000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  5184 000022C7 A801                <1> 	test	al, 1
  5185                              <1> 	;jnz	short drst6
  5186 000022C9 7516                <1>         jnz     short drst4
  5187 000022CB 8065FDEF            <1> 	and	byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0
  5188                              <1> ;drst5:
  5189                              <1> drst3:
  5190 000022CF E89F000000          <1> 	call	INIT_DRV		; SET MAX HEADS
  5191                              <1> 	;mov	dx, di
  5192 000022D4 E82F010000          <1> 	call	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  5193                              <1> 	; 04/01/2014
  5194                              <1> ;	inc	di
  5195                              <1> ;	mov	dx, di
  5196                              <1> ;	cmp	dl, [HF_NUM]
  5197                              <1> ;	jb	short drst3
  5198                              <1> ;DRE:
  5199 000022D9 C605[6B650000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; IGNORE ANY SET UP ERRORS
  5200 000022E0 C3                  <1> 	retn
  5201                              <1> ;drst6:
  5202                              <1> drst4:		; Drive/Head Register - bit 4
  5203 000022E1 804DFD10            <1> 	or	byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1     
  5204                              <1>         ;jmp    short drst5
  5205 000022E5 EBE8                <1>         jmp     short drst3
  5206                              <1> 
  5207                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5208                              <1> 
  5209                              <1> ;----------------------------------------
  5210                              <1> ;	DISK READ ROUTINE    (AH = 01H) :
  5211                              <1> ;----------------------------------------
  5212                              <1> ; 
  5213                              <1> DISK_READ:
  5214 000022E7 C645FE20            <1> 	mov	byte [CMD_BLOCK+6], READ_CMD
  5215                              <1>         ;jmp	COMMANDI
  5216                              <1> 
  5217                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5218                              <1> 
  5219                              <1> ;----------------------------------------
  5220                              <1> ; COMMANDI				:
  5221                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  5222                              <1> ;	NSECTOR RETURNS ZERO		:
  5223                              <1> ;----------------------------------------
  5224                              <1> COMMANDI:
  5225 000022EB E8A3020000          <1> 	call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5226 000022F0 722D                <1> 	jc	short CMD_ABORT
  5227                              <1> 	;mov	di, bx
  5228 000022F2 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  5229 000022F4 E845010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5230 000022F9 7524                <1> 	jnz	short CMD_ABORT
  5231                              <1> CMD_I1:
  5232 000022FB E8B0010000          <1> 	call	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  5233 00002300 751D                <1> 	jnz	short TM_OUT		; TIME OUT
  5234                              <1> 	;;mov	cx,256			; SECTOR SIZE IN WORDS
  5235                              <1> 	;mov	ecx, 256 ; 21/02/2015	
  5236 00002302 29C9                <1> 	sub	ecx, ecx
  5237 00002304 FEC5                <1> 	inc	ch
  5238                              <1> 	; ecx = 256
  5239                              <1> 	;mov	dx, HF_PORT
  5240 00002306 668B15[C45F0000]    <1> 	mov	dx, [HF_PORT]
  5241 0000230D FA                  <1> 	cli
  5242 0000230E FC                  <1> 	cld
  5243 0000230F F3666D              <1> 	rep	insw			; GET THE SECTOR
  5244 00002312 FB                  <1> 	sti
  5245                              <1> 	
  5246                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT
  5247                              <1> 	;jz	short CMD_I3
  5248                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5249                              <1> 	;jc	short TM_OUT
  5250                              <1> 	;;mov	dx, HF_PORT
  5251                              <1> 	;mov	dx,[HF_PORT]
  5252                              <1> 	;xor	ecx, ecx	
  5253                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5254                              <1> 	;mov	cl, 4
  5255                              <1> ;CMD_I2: 
  5256                              <1> 	;inc	al, dx
  5257                              <1> 	;mov 	[edi], al ; 21/02/2015
  5258                              <1> 	;inc	edi
  5259                              <1> 	;loop	CMD_I2
  5260                              <1> CMD_I3: 
  5261 00002313 E8B4000000          <1> 	call	CHECK_STATUS
  5262 00002318 7505                <1> 	jnz	short CMD_ABORT		; ERROR RETURNED
  5263 0000231A FE4DF9              <1> 	dec	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  5264 0000231D 75DC                <1> 	jnz	SHORT CMD_I1
  5265                              <1> CMD_ABORT:
  5266                              <1> TM_OUT: 
  5267 0000231F C3                  <1> 	retn
  5268                              <1> 
  5269                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5270                              <1> 
  5271                              <1> ;----------------------------------------
  5272                              <1> ;	DISK WRITE ROUTINE   (AH = 02H) :
  5273                              <1> ;----------------------------------------
  5274                              <1> 
  5275                              <1> DISK_WRITE:
  5276 00002320 C645FE30            <1> 	mov	byte [CMD_BLOCK+6], WRITE_CMD
  5277                              <1>         ;JMP	COMMANDO
  5278                              <1> 
  5279                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5280                              <1> 
  5281                              <1> ;----------------------------------------
  5282                              <1> ; COMMANDO				:
  5283                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  5284                              <1> ;	NSECTOR RETURNS ZERO		:
  5285                              <1> ;----------------------------------------
  5286                              <1> COMMANDO:
  5287 00002324 E86A020000          <1> 	call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5288 00002329 72F4                <1> 	jc	short CMD_ABORT
  5289                              <1> CMD_OF:
  5290 0000232B 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5291 0000232D E80C010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5292 00002332 75EB                <1> 	jnz	short CMD_ABORT
  5293 00002334 E8CE010000          <1> 	call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5294 00002339 72E4                <1> 	jc	short TM_OUT			; TOO LONG
  5295                              <1> CMD_O1:
  5296                              <1> 	; 10/07/2022
  5297                              <1> 	;mov	ecx, 256 ; 21/02/2015
  5298 0000233B 31C9                <1> 	xor	ecx, ecx
  5299 0000233D FEC5                <1> 	inc	ch
  5300                              <1> 	; ecx = 256
  5301 0000233F FA                  <1> 	cli
  5302 00002340 FC                  <1> 	cld
  5303 00002341 F3666F              <1> 	rep	outsw
  5304 00002344 FB                  <1> 	sti
  5305                              <1> 
  5306                              <1> 	; 10/07/2022
  5307                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT
  5308                              <1> 	;jz	short CMD_O3
  5309                              <1> 	;
  5310                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5311                              <1> 	;jc	short TM_OUT
  5312                              <1> 	;;mov	dx, HF_PORT
  5313                              <1> 	;mov	dx, [HF_PORT]
  5314                              <1> 	;sub	ecx, ecx	
  5315                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5316                              <1> 	;mov	cl, 4
  5317                              <1> ;CMD_O2:
  5318                              <1> 	;;lodsb
  5319                              <1> 	;mov	al, [esi]
  5320                              <1> 	;out	dx, al
  5321                              <1> 	;inc	esi
  5322                              <1> 	;loop	CMD_O2
  5323                              <1> 
  5324                              <1> CMD_O3:
  5325 00002345 E866010000          <1> 	call	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  5326 0000234A 75D3                <1> 	jnz	short TM_OUT		; ERROR RETURNED
  5327 0000234C E87B000000          <1> 	call	CHECK_STATUS
  5328 00002351 75CC                <1> 	jnz	short CMD_ABORT
  5329 00002353 F605[65650000]08    <1> 	test	byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE
  5330 0000235A 75DF                <1> 	jnz	short CMD_O1
  5331                              <1> 	;mov	dx, HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  5332 0000235C 668B15[C45F0000]    <1> 	mov	dx, [HF_PORT]
  5333 00002363 80C202              <1> 	add	dl, 2
  5334                              <1> 	;inc	dl
  5335                              <1> 	;inc	dl
  5336 00002366 EC                  <1> 	in	al, dx			;
  5337 00002367 A8FF                <1> 	test	al, 0FFh 		;
  5338 00002369 7407                <1> 	jz	short CMD_O4			; COUNT = 0  OK
  5339 0000236B C605[6B650000]BB    <1> 	mov	byte [DISK_STATUS1], UNDEF_ERR 
  5340                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  5341                              <1> CMD_O4:
  5342 00002372 C3                  <1> 	retn
  5343                              <1> 
  5344                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5345                              <1> 
  5346                              <1> ;----------------------------------------
  5347                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  5348                              <1> ;----------------------------------------
  5349                              <1> 	; 03/01/2015
  5350                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  5351                              <1> 	; logical sector per logical track
  5352                              <1> 	; and logical heads - 1 would be set but
  5353                              <1> 	; it is seen as it will be good
  5354                              <1> 	; if physical parameters will be set here
  5355                              <1> 	; because, number of heads <= 16.
  5356                              <1> 	; (logical heads usually more than 16)
  5357                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  5358                              <1> 	;	== INT 13h physical parameters
  5359                              <1> 
  5360                              <1> ;INIT_DRV:
  5361                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  5362                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  5363                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  5364                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  5365                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  5366                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  5367                              <1> ;	OR	AH,AL			; TO MAX HEAD
  5368                              <1> ;	MOV	[CMD_BLOCK+5],AH
  5369                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  5370                              <1> ;	MOV	[CMD_BLOCK+1],AL
  5371                              <1> ;	SUB	AX,AX
  5372                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  5373                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  5374                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  5375                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  5376                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  5377                              <1> ;	CALL	CHECK_STATUS
  5378                              <1> ;INIT_EXIT:
  5379                              <1> ;	RETn
  5380                              <1> 
  5381                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5382                              <1> 
  5383                              <1> ; 04/01/2015
  5384                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  5385                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  5386                              <1> INIT_DRV:
  5387                              <1> 	;xor	ah, ah
  5388 00002373 31C0                <1> 	xor	eax, eax ; 21/02/2015
  5389 00002375 B00B                <1> 	mov	al, 11 ; Physical heads from translated HDPT
  5390 00002377 3825[80650000]      <1>         cmp     [LBAMode], ah   ; 0
  5391 0000237D 7702                <1> 	ja	short idrv0
  5392 0000237F B002                <1> 	mov	al, 2  ; Physical heads from standard HDPT
  5393                              <1> idrv0:
  5394                              <1> 	; DL = drive number (0 based)
  5395 00002381 E824020000          <1> 	call	GET_VEC
  5396                              <1> 	;push	bx
  5397 00002386 53                  <1> 	push	ebx ; 21/02/2015
  5398                              <1> 	;add	bx, ax
  5399 00002387 01C3                <1> 	add	ebx, eax
  5400                              <1> 	;; 05/01/2015
  5401 00002389 8A25[C85F0000]      <1> 	mov	ah, [hf_m_s] ; drive number (0= master, 1= slave)
  5402                              <1> 	;;and 	ah, 1 
  5403 0000238F C0E404              <1> 	shl	ah, 4
  5404 00002392 80CCA0              <1> 	or	ah, 0A0h  ; Drive/Head register - 10100000b (A0h)	
  5405                              <1> 	;mov	al, [es:bx]
  5406 00002395 8A03                <1> 	mov	al, [ebx] ; 21/02/2015
  5407 00002397 FEC8                <1> 	dec	al	 ; last head number 
  5408                              <1> 	;and	al, 0Fh
  5409 00002399 08E0                <1> 	or	al, ah	 ; lower 4 bits for head number
  5410                              <1> 	;
  5411 0000239B C645FE91            <1> 	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5412 0000239F 8845FD              <1> 	mov	[CMD_BLOCK+5], al
  5413                              <1> 	;pop	bx
  5414 000023A2 5B                  <1> 	pop	ebx
  5415 000023A3 29C0                <1> 	sub	eax, eax ; 21/02/2015
  5416 000023A5 B004                <1> 	mov	al, 4 ; Physical sec per track from translated HDPT
  5417 000023A7 803D[80650000]00    <1> 	cmp	byte [LBAMode], 0
  5418 000023AE 7702                <1> 	ja	short idrv1
  5419 000023B0 B00E                <1> 	mov	al, 14 ; Physical sec per track from standard HDPT
  5420                              <1> idrv1:
  5421                              <1> 	;xor	ah, ah
  5422                              <1> 	;add	bx, ax
  5423 000023B2 01C3                <1> 	add	ebx, eax ; 21/02/2015
  5424                              <1> 	;mov	al, [es:bx]
  5425                              <1> 			; sector number
  5426 000023B4 8A03                <1> 	mov	al, [ebx]
  5427 000023B6 8845F9              <1> 	mov	[CMD_BLOCK+1], al
  5428 000023B9 28C0                <1> 	sub	al, al
  5429 000023BB 8845FB              <1> 	mov	[CMD_BLOCK+3], al ; ZERO FLAGS
  5430 000023BE E87B000000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  5431 000023C3 751E                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  5432 000023C5 E816010000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  5433 000023CA 7517                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  5434                              <1> 	;call	CHECK_STATUS
  5435                              <1> 	;jmp	short CHECK_STATUS
  5436                              <1> ;INIT_EXIT:
  5437                              <1> 	;retn
  5438                              <1> 
  5439                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5440                              <1> 
  5441                              <1> ;----------------------------------------
  5442                              <1> ;	CHECK FIXED DISK STATUS 	:
  5443                              <1> ;----------------------------------------
  5444                              <1> CHECK_STATUS:
  5445 000023CC E861010000          <1> 	call	CHECK_ST		; CHECK THE STATUS BYTE
  5446                              <1> 	;jnz	short CHECK_S1		; AN ERROR WAS FOUND
  5447                              <1> 	; 10/07/2022
  5448 000023D1 7510                <1> 	jnz	short CHECK_S2
  5449 000023D3 A801                <1> 	test	al, ST_ERROR		; WERE THERE ANY OTHER ERRORS
  5450 000023D5 7405                <1> 	jz	short CHECK_S1		; NO ERROR REPORTED
  5451 000023D7 E894010000          <1> 	call	CHECK_ER		; ERROR REPORTED
  5452                              <1> CHECK_S1:
  5453 000023DC 803D[6B650000]00    <1> 	cmp	byte [DISK_STATUS1], 0 	; SET STATUS FOR CALLER
  5454                              <1> CHECK_S2:
  5455                              <1> INIT_EXIT:	; 10/07/2022
  5456 000023E3 C3                  <1> 	retn
  5457                              <1> 
  5458                              <1> ;----------------------------------------
  5459                              <1> ;	TEST DISK READY      (AH = 10H) :
  5460                              <1> ;----------------------------------------
  5461                              <1> 
  5462                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  5463 000023E4 E8F7000000          <1> 	call	NOT_BUSY
  5464 000023E9 751C                <1> 	jnz	short TR_EX
  5465 000023EB 8A45FD              <1> 	mov	al, [CMD_BLOCK+5] 	; SELECT DRIVE
  5466 000023EE 668B15[C45F0000]    <1> 	mov	dx, [HF_PORT]
  5467 000023F5 80C206              <1> 	add	dl,6
  5468 000023F8 EE                  <1> 	out	dx, al
  5469 000023F9 E834010000          <1> 	call	CHECK_ST		; CHECK STATUS ONLY
  5470 000023FE 7507                <1> 	jnz	short TR_EX
  5471 00002400 C605[6B650000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; WIPE OUT DATA CORRECTED ERROR
  5472                              <1> TR_EX:	
  5473 00002407 C3                  <1> 	retn
  5474                              <1> 
  5475                              <1> ;----------------------------------------
  5476                              <1> ;	RECALIBRATE	     (AH = 11H) :
  5477                              <1> ;----------------------------------------
  5478                              <1> 
  5479                              <1> HDISK_RECAL:
  5480 00002408 C645FE10            <1>         mov	byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16
  5481 0000240C E82D000000          <1> 	call	COMMAND 		; START THE OPERATION
  5482 00002411 7523                <1> 	jnz	short RECAL_EXIT	; ERROR
  5483 00002413 E898000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION
  5484 00002418 7407                <1> 	jz	short RECAL_X 		; TIME OUT ONE OK ?
  5485 0000241A E891000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION LONGER
  5486 0000241F 7515                <1> 	jnz	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  5487                              <1> RECAL_X:
  5488 00002421 E8A6FFFFFF          <1> 	call	CHECK_STATUS
  5489 00002426 803D[6B650000]40    <1> 	cmp	byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE
  5490 0000242D 7507                <1> 	jne	short RECAL_EXIT	; IS OK
  5491 0000242F C605[6B650000]00    <1> 	mov	byte [DISK_STATUS1], 0
  5492                              <1> RECAL_EXIT:
  5493 00002436 803D[6B650000]00    <1>         cmp	byte [DISK_STATUS1], 0
  5494 0000243D C3                  <1> 	retn
  5495                              <1> 
  5496                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5497                              <1> 
  5498                              <1> ;--------------------------------------------------------
  5499                              <1> ; COMMAND						:
  5500                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  5501                              <1> ; OUTPUT						:
  5502                              <1> ;	BL = STATUS					:
  5503                              <1> ;	BH = ERROR REGISTER				:
  5504                              <1> ;--------------------------------------------------------
  5505                              <1> 
  5506                              <1> COMMAND:
  5507                              <1> 	;push	ebx ; 10/07/2022	; WAIT FOR SEEK COMPLETE AND READY
  5508                              <1> 	;;mov	ecx, DELAY_2		; SET INITIAL DELAY BEFORE TEST
  5509                              <1> COMMAND1:
  5510                              <1> 	;;push	ecx			; SAVE LOOP COUNT
  5511 0000243E E8A1FFFFFF          <1> 	call	TST_RDY 		; CHECK DRIVE READY
  5512                              <1> 	;;pop	ecx
  5513                              <1> 	;pop	ebx ; 10/07/2022
  5514 00002443 7418                <1> 	jz	short COMMAND2		; DRIVE IS READY
  5515 00002445 803D[6B650000]80    <1>         cmp	byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  5516                              <1> 	;jz	short CMD_TIMEOUT
  5517                              <1> 	;;loop	COMMAND1		; KEEP TRYING FOR A WHILE
  5518                              <1> 	;jmp	short COMMAND4		; ITS NOT GOING TO GET READY
  5519 0000244C 7507                <1> 	jne	short COMMAND4
  5520                              <1> CMD_TIMEOUT:
  5521 0000244E C605[6B650000]20    <1> 	mov	byte [DISK_STATUS1], BAD_CNTLR
  5522                              <1> COMMAND4:
  5523                              <1> 	;;pop	ebx ; 10/07/2022
  5524 00002455 803D[6B650000]00    <1>         cmp	byte [DISK_STATUS1], 0	; SET CONDITION CODE FOR CALLER
  5525 0000245C C3                  <1> 	retn
  5526                              <1> COMMAND2:
  5527                              <1> 	;;pop	ebx ; 10/07/2022
  5528                              <1> 	;push	edi ; 10/07/2022
  5529 0000245D C605[66650000]00    <1> 	mov	byte [HF_INT_FLAG], 0	; RESET INTERRUPT FLAG
  5530 00002464 FA                  <1> 	cli				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  5531 00002465 E4A1                <1> 	in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  5532                              <1> 	;and	al, 0BFh
  5533 00002467 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  5534                              <1> 	;JMP	$+2
  5535                              <1> 	IODELAY
  2160 00002469 EB00                <2>  jmp short $+2
  2161 0000246B EB00                <2>  jmp short $+2
  5536 0000246D E6A1                <1> 	out	INTB01, al
  5537 0000246F E421                <1> 	in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  5538 00002471 24FB                <1> 	and	al, 0FBh 		; SECOND CHIP
  5539                              <1> 	;JMP	$+2
  5540                              <1> 	IODELAY
  2160 00002473 EB00                <2>  jmp short $+2
  2161 00002475 EB00                <2>  jmp short $+2
  5541 00002477 E621                <1> 	out	INTA01, al
  5542 00002479 FB                  <1> 	sti
  5543                              <1> 	;xor	edi, edi		; INDEX THE COMMAND TABLE
  5544                              <1> 	; 10/07/2022
  5545 0000247A 31C9                <1> 	xor	ecx, ecx
  5546                              <1> 	;mov	dx, HF_PORT+1		; DISK ADDRESS
  5547 0000247C 668B15[C45F0000]    <1> 	mov	dx, [HF_PORT]
  5548 00002483 FEC2                <1> 	inc	dl
  5549 00002485 F605[6D650000]C0    <1> 	test	byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION
  5550 0000248C 7411                <1> 	jz	short COMMAND3
  5551 0000248E 8A45FE              <1> 	mov	al, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  5552 00002491 24F0                <1> 	and	al, 0F0h 		; GET RID OF MODIFIERS
  5553 00002493 3C20                <1> 	cmp	al, 20h			; 20H-40H IS READ, WRITE, VERIFY
  5554 00002495 7208                <1> 	jb	short COMMAND3
  5555 00002497 3C40                <1> 	cmp	al, 40h
  5556 00002499 7704                <1> 	ja	short COMMAND3
  5557 0000249B 804DFE01            <1> 	or	byte [CMD_BLOCK+6], NO_RETRIES 
  5558                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  5559                              <1> COMMAND3:
  5560                              <1> 	;mov	al, [CMD_BLOCK+edi]	; GET THE COMMAND STRING BYTE
  5561                              <1> 	; 10/07/2022
  5562 0000249F 8A440DF8            <1> 	mov	al, [CMD_BLOCK+ecx]
  5563 000024A3 EE                  <1> 	out	dx, al			; GIVE IT TO CONTROLLER
  5564                              <1> 	IODELAY
  2160 000024A4 EB00                <2>  jmp short $+2
  2161 000024A6 EB00                <2>  jmp short $+2
  5565                              <1> 	;inc	edi			; NEXT BYTE IN COMMAND BLOCK
  5566                              <1> 	; 10/07/2022
  5567 000024A8 41                  <1> 	inc	ecx
  5568                              <1> 	;inc	dx			; NEXT DISK ADAPTER REGISTER
  5569 000024A9 42                  <1> 	inc	edx   ; 10/07/2022	
  5570                              <1> 	;cmp	di, 7 ; 01/01/2015	; ALL DONE?
  5571                              <1> 	;jne	short COMMAND3		; NO--GO DO NEXT ONE
  5572 000024AA 80F907              <1> 	cmp	cl, 7 ; 10/07/2022
  5573 000024AD 72F0                <1> 	jb	short COMMAND3
  5574                              <1> 	;pop	edi ; 10/07/2022
  5575 000024AF C3                  <1> 	retn				; ZERO FLAG IS SET
  5576                              <1> 
  5577                              <1> ;CMD_TIMEOUT:
  5578                              <1> ;	mov	byte [DISK_STATUS1], BAD_CNTLR
  5579                              <1> ;COMMAND4:
  5580                              <1> ;	pop	ebx
  5581                              <1> ;	cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5582                              <1> ;	retn
  5583                              <1> 
  5584                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5585                              <1> 
  5586                              <1> ;----------------------------------------
  5587                              <1> ;	WAIT FOR INTERRUPT		:
  5588                              <1> ;----------------------------------------
  5589                              <1> ;WAIT:
  5590                              <1> _WAIT:
  5591 000024B0 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5592                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5593                              <1> 	;clc
  5594                              <1> 	;mov	ax, 9000h		; DEVICE WAIT INTERRUPT
  5595                              <1> 	;int	15h
  5596                              <1> 	;jc	short WT2		; DEVICE TIMED OUT
  5597                              <1> 	;mov	bl, DELAY_1		; SET DELAY COUNT
  5598                              <1> 
  5599                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  5600                              <1> 	;; 21/02/2015
  5601                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  5602                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  5603 000024B1 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  5604                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  5605                              <1> ;-----	WAIT LOOP
  5606                              <1> 
  5607                              <1> WT1:	
  5608                              <1> 	;test	byte [HF_INT_FLAG], 80h	; TEST FOR INTERRUPT
  5609 000024B6 F605[66650000]C0    <1> 	test 	byte [HF_INT_FLAG], 0C0h
  5610                              <1> 	;loopz	WT1
  5611 000024BD 7512                <1> 	jnz	short WT3		; INTERRUPT--LETS GO
  5612                              <1> 	;dec	bl
  5613                              <1> 	;jnz	short WT1		; KEEP TRYING FOR A WHILE
  5614                              <1> 
  5615                              <1> WT1_hi:
  5616 000024BF E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  5617 000024C1 A810                <1> 	test	al, 10h			; transition on memory
  5618 000024C3 75FA                <1> 	jnz	short WT1_hi		; refresh.
  5619                              <1> WT1_lo:
  5620 000024C5 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  5621 000024C7 A810                <1> 	test	al, 10h			
  5622 000024C9 74FA                <1> 	jz	short WT1_lo
  5623 000024CB E2E9                <1> 	loop	WT1
  5624                              <1> 	;;or	bl, bl
  5625                              <1> 	;;jz	short WT2	
  5626                              <1> 	;;dec	bl
  5627                              <1> 	;;jmp	short WT1
  5628                              <1> 	;dec	bl
  5629                              <1> 	;jnz	short WT1	
  5630                              <1> WT2:	
  5631                              <1> 	; 10/07/2022
  5632                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5633 000024CD B080                <1> 	mov	al, TIME_OUT
  5634 000024CF EB07                <1> 	jmp	short WT4
  5635                              <1> WT3:
  5636                              <1> 	;mov	byte [DISK_STATUS1], 0
  5637                              <1> 	;mov	byte [HF_INT_FLAG], 0
  5638 000024D1 28C0                <1> 	sub	al, al ; 0
  5639 000024D3 A2[66650000]        <1> 	mov	byte [HF_INT_FLAG], al
  5640                              <1> WT4:
  5641                              <1> NB2:	
  5642 000024D8 A2[6B650000]        <1> 	mov	byte [DISK_STATUS1], al
  5643                              <1> 
  5644                              <1> 	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5645 000024DD 20C0                <1> 	and	al, al
  5646                              <1> 	; zf = 0 -> time out, zf = 1 -> ok
  5647 000024DF C3                  <1> 	retn
  5648                              <1> 
  5649                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5650                              <1> 
  5651                              <1> ;----------------------------------------
  5652                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  5653                              <1> ;----------------------------------------
  5654                              <1> NOT_BUSY:
  5655 000024E0 FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5656                              <1> 	;push	ebx
  5657                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5658 000024E1 668B15[C45F0000]    <1> 	mov	dx, [HF_PORT]
  5659 000024E8 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  5660                              <1> 	;mov	bl, DELAY_1
  5661                              <1> 					; wait for 10 seconds
  5662                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  5663                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  5664                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  5665 000024EB B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  5666                              <1> 	;
  5667                              <1> 	;;mov	byte [wait_count], 0    ; Reset wait counter
  5668                              <1> NB1:	
  5669 000024F0 EC                  <1> 	in	al, dx			; CHECK STATUS
  5670                              <1> 	;test	al, ST_BUSY
  5671 000024F1 2480                <1> 	and	al, ST_BUSY
  5672                              <1> 	;loopnz NB1
  5673 000024F3 74E3                <1> 	jz	short NB2 ; al = 0	; NOT BUSY--LETS GO
  5674                              <1> 	;dec	bl			
  5675                              <1> 	;jnz	short NB1		; KEEP TRYING FOR A WHILE
  5676                              <1> 
  5677                              <1> NB1_hi: 
  5678 000024F5 E461                <1> 	in	al, SYS1		; wait for hi to lo
  5679 000024F7 A810                <1> 	test	al, 010h		; transition on memory
  5680 000024F9 75FA                <1> 	jnz	short NB1_hi		; refresh.
  5681                              <1> NB1_lo: 
  5682 000024FB E461                <1> 	in	al, SYS1
  5683 000024FD A810                <1> 	test	al, 010h
  5684 000024FF 74FA                <1> 	jz	short NB1_lo
  5685 00002501 E2ED                <1> 	loop	NB1
  5686                              <1> 	;dec	bl
  5687                              <1> 	;jnz	short NB1
  5688                              <1> 	;
  5689                              <1> 	;;cmp	byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  5690                              <1> 	;;jb	short NB1
  5691                              <1> 	;
  5692                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5693                              <1> 	;jmp	short NB3
  5694 00002503 B080                <1> 	mov	al, TIME_OUT
  5695                              <1> ;NB2:	
  5696 00002505 EBD1                <1> 	jmp	short NB2 ; 10/07/2022
  5697                              <1> 
  5698                              <1> ;	;mov	byte [DISK_STATUS1], 0
  5699                              <1> ;;NB3:	
  5700                              <1> ;	;pop	ebx
  5701                              <1> ;	mov	[DISK_STATUS1], al	;;; will be set after return
  5702                              <1> ;	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5703                              <1> ;	or	al, al			; (zf = 0 --> timeout)
  5704                              <1> ;	retn
  5705                              <1> 
  5706                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5707                              <1> 
  5708                              <1> ;----------------------------------------
  5709                              <1> ;	WAIT FOR DATA REQUEST		:
  5710                              <1> ;----------------------------------------
  5711                              <1> WAIT_DRQ:
  5712                              <1> 	;mov	cx, DELAY_3
  5713                              <1> 	;mov	dx, HF_PORT+7
  5714 00002507 668B15[C45F0000]    <1> 	mov	dx, [HF_PORT]
  5715 0000250E 80C207              <1> 	add	dl, 7
  5716                              <1> 	;;mov	bl, WAIT_HDU_DRQ_HI	; 0
  5717                              <1> 	;mov	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  5718                              <1> 					; (but it is written as 2000
  5719                              <1> 					; micro seconds in ATORGS.ASM file
  5720                              <1> 					; of Award Bios - 1999, D1A0622)
  5721 00002511 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  5722                              <1> WQ_1:
  5723 00002516 EC                  <1> 	in	al, dx			; GET STATUS
  5724 00002517 A808                <1> 	test	al, ST_DRQ		; WAIT FOR DRQ
  5725 00002519 7516                <1> 	jnz	short WQ_OK
  5726                              <1> 	;loop	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  5727                              <1> WQ_hi:	
  5728 0000251B E461                <1> 	in	al, SYS1		; wait for hi to lo
  5729 0000251D A810                <1> 	test	al, 010h		; transition on memory
  5730 0000251F 75FA                <1> 	jnz	short WQ_hi		; refresh.
  5731                              <1> WQ_lo:  
  5732 00002521 E461                <1> 	in	al, SYS1
  5733 00002523 A810                <1> 	test	al, 010h
  5734 00002525 74FA                <1> 	jz	short WQ_lo
  5735 00002527 E2ED                <1> 	loop	WQ_1
  5736                              <1> 
  5737 00002529 C605[6B650000]80    <1> 	mov	byte [DISK_STATUS1], TIME_OUT ; ERROR
  5738 00002530 F9                  <1> 	stc
  5739                              <1> WQ_OK:
  5740 00002531 C3                  <1> 	retn
  5741                              <1> ;WQ_OK:
  5742                              <1> 	;clc
  5743                              <1> 	;retn
  5744                              <1> 
  5745                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5746                              <1> 
  5747                              <1> ;----------------------------------------
  5748                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  5749                              <1> ;----------------------------------------
  5750                              <1> CHECK_ST:
  5751                              <1> 	;mov	dx, HF_PORT+7		; GET THE STATUS
  5752 00002532 668B15[C45F0000]    <1> 	mov	dx, [HF_PORT]
  5753 00002539 80C207              <1> 	add	dl, 7
  5754 0000253C EC                  <1> 	in	al, dx
  5755 0000253D A2[65650000]        <1> 	mov	[HF_STATUS], al
  5756                              <1> 	;mov	ah, 0
  5757 00002542 28E4                <1> 	sub	ah, ah ; 0
  5758 00002544 A880                <1> 	test	al, ST_BUSY		; IF STILL BUSY
  5759 00002546 751A                <1> 	jnz	short CKST_EXIT		; REPORT OK
  5760 00002548 B4CC                <1> 	mov	ah, WRITE_FAULT
  5761 0000254A A820                <1> 	test 	al, ST_WRT_FLT		; CHECK FOR WRITE FAULT
  5762 0000254C 7514                <1> 	jnz	short CKST_EXIT
  5763 0000254E B4AA                <1> 	mov	ah, NOT_RDY
  5764 00002550 A840                <1> 	test	al, ST_READY		; CHECK FOR NOT READY
  5765 00002552 740E                <1> 	jz	short CKST_EXIT
  5766 00002554 B440                <1> 	mov	ah, BAD_SEEK
  5767 00002556 A810                <1> 	test	al, ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  5768 00002558 7408                <1> 	jz	short CKST_EXIT
  5769 0000255A B411                <1> 	mov	ah, DATA_CORRECTED
  5770 0000255C A804                <1> 	test	al, ST_CORRCTD		; CHECK FOR CORRECTED ECC
  5771 0000255E 7502                <1> 	jnz	short CKST_EXIT
  5772                              <1> 	;mov	ah, 0
  5773 00002560 30E4                <1> 	xor	ah, ah ; 0
  5774                              <1> CKST_EXIT:
  5775 00002562 8825[6B650000]      <1> 	mov	[DISK_STATUS1], ah	; SET ERROR FLAG
  5776 00002568 80FC11              <1> 	cmp	ah, DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  5777 0000256B 7402                <1> 	je	short CKST_EX1
  5778                              <1> 	;cmp	ah, 0
  5779 0000256D 20E4                <1> 	and	ah, ah
  5780                              <1> CKST_EX1:
  5781 0000256F C3                  <1> 	retn
  5782                              <1> 
  5783                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5784                              <1> 
  5785                              <1> ;----------------------------------------
  5786                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  5787                              <1> ;----------------------------------------
  5788                              <1> CHECK_ER:
  5789                              <1> 	;mov	dx, HF_PORT+1		; GET THE ERROR REGISTER
  5790 00002570 668B15[C45F0000]    <1> 	mov	dx, [HF_PORT]		;
  5791 00002577 FEC2                <1> 	inc	dl
  5792 00002579 EC                  <1> 	in	al, dx
  5793                              <1> 	; 10/07/2022
  5794                              <1> 	;mov	[HF_ERROR], al
  5795                              <1> 	;push	ebx	; 21/02/2015
  5796 0000257A 29C9                <1> 	sub	ecx, ecx
  5797                              <1> 	;mov	ecx, 8			; TEST ALL 8 BITS
  5798 0000257C B108                <1> 	mov	cl, 8
  5799                              <1> CK1:	
  5800 0000257E D0E0                <1> 	shl	al, 1			; MOVE NEXT ERROR BIT TO CARRY
  5801 00002580 7202                <1> 	jc	short CK2		; FOUND THE ERROR
  5802 00002582 E2FA                <1> 	loop	CK1			; KEEP TRYING
  5803                              <1> CK2:
  5804                              <1> 	;mov	ebx, ERR_TBL		; COMPUTE ADDRESS OF
  5805                              <1> 	;add	ebx, ecx		; ERROR CODE
  5806 00002584 81C1[B85F0000]      <1> 	add	ecx, ERR_TBL ; 10/07/2022	
  5807                              <1> 
  5808                              <1> 	;;;mov	ah, byte [cs:bx]	; GET ERROR CODE
  5809                              <1> 	;;mov	ah, [bx]
  5810                              <1> 	;mov	ah, [ebx] ; 21/02/2015
  5811 0000258A 8A21                <1> 	mov	ah, [ecx]	
  5812                              <1> CKEX:
  5813 0000258C 8825[6B650000]      <1> 	mov	[DISK_STATUS1], ah	; SAVE ERROR CODE
  5814                              <1> 	; 10/07/2022
  5815                              <1> 	;pop	ebx
  5816                              <1> 	;;cmp	ah, 0
  5817                              <1> 	;and	ah, ah
  5818 00002592 C3                  <1> 	retn
  5819                              <1> 
  5820                              <1> ;--------------------------------------------------------
  5821                              <1> ; CHECK_DMA						:
  5822                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  5823                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  5824                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  5825                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  5826                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  5827                              <1> ;  -ERROR OTHERWISE					:
  5828                              <1> ;--------------------------------------------------------
  5829                              <1> 
  5830                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5831                              <1> CHECK_DMA:
  5832                              <1> 	;;push	ax			; SAVE REGISTERS
  5833                              <1> 	;; 24/12/2021
  5834                              <1> 	;;push	eax
  5835                              <1> 	;mov	ax, 8000h		; AH = MAX # SECTORS
  5836                              <1> 					; AL = MAX OFFSET
  5837                              <1> 	; 10/07/2022
  5838                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE
  5839                              <1> 	;jz	short CKD1
  5840                              <1> 	;mov	ax, 7F04h		; ECC IS 4 MORE BYTES
  5841                              <1> CKD1:	
  5842                              <1> 	;cmp	ah, [CMD_BLOCK+1]	; NUMBER OF SECTORS
  5843                              <1> 	;ja	short CKDOK		; IT WILL FIT
  5844                              <1> 	;jb	short CKDERR		; TOO MANY
  5845 00002593 807DF980            <1> 	cmp	byte [CMD_BLOCK+1], 80h
  5846 00002597 720F                <1> 	jb	short CKDOK
  5847 00002599 7704                <1> 	ja	short CKDERR
  5848                              <1> 	;cmp	al, bl			; CHECK OFFSET ON MAX SECTORS
  5849                              <1> 	;jb	short CKDERR		; ERROR
  5850                              <1> CKD2:
  5851 0000259B 08DB                <1> 	or	bl, bl
  5852 0000259D 740A                <1> 	jz	short CKDR
  5853                              <1> 	
  5854                              <1> ;CKDOK:	
  5855                              <1> 	;clc				; CLEAR CARRY
  5856                              <1> 	;;pop	ax
  5857                              <1> 	;; 24/12/2021
  5858                              <1> 	;pop	eax
  5859                              <1> 	;retn				; NORMAL RETURN
  5860                              <1> CKDERR: 
  5861 0000259F F9                  <1> 	stc				; INDICATE ERROR
  5862 000025A0 C605[6B650000]09    <1>         mov	byte [DISK_STATUS1], DMA_BOUNDARY
  5863                              <1> 	;;pop	ax
  5864                              <1> 	;; 24/12/2021
  5865                              <1> 	;pop	eax	
  5866 000025A7 C3                  <1> 	retn
  5867                              <1> 
  5868                              <1> 	; 10/07/2022
  5869                              <1> CKDOK:
  5870 000025A8 F8                  <1> 	clc
  5871                              <1> CKDR:
  5872 000025A9 C3                  <1> 	retn
  5873                              <1> 
  5874                              <1> ;----------------------------------------
  5875                              <1> ;	SET UP EBX-> DISK PARMS	        :
  5876                              <1> ;----------------------------------------
  5877                              <1> 					
  5878                              <1> ; INPUT -> DL = 0 based drive number
  5879                              <1> ; OUTPUT -> EBX = disk parameter table address
  5880                              <1> 
  5881                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5882                              <1> 
  5883                              <1> GET_VEC:
  5884                              <1> 	;sub	ax, ax			; GET DISK PARAMETER ADDRESS
  5885                              <1> 	;mov	es, ax
  5886                              <1> 	;test	dl, 1
  5887                              <1> 	;jz	short GV_0
  5888                              <1> ;	les	bx, [HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  5889                              <1> ;	jmp	short GV_EXIT
  5890                              <1> ;GV_0:
  5891                              <1> ;	les 	bx,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  5892                              <1> ;
  5893 000025AA 31DB                <1> 	xor	ebx, ebx
  5894 000025AC 88D3                <1> 	mov	bl, dl
  5895                              <1> 	;02/01/2015
  5896                              <1> 	;xor	bh, bh
  5897                              <1> 	;shl	bl, 1			; port address offset
  5898                              <1> 	;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  5899                              <1> 	;shl	bl, 1			; dpt pointer offset
  5900 000025AE C0E302              <1> 	shl	bl, 2
  5901                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  5902 000025B1 81C3[70650000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  5903                              <1> 	;push	word [bx+2]		; dpt segment
  5904                              <1> 	;pop	es
  5905                              <1> 	;mov	bx, [bx]		; dpt offset
  5906 000025B7 8B1B                <1> 	mov	ebx, [ebx]		
  5907                              <1> ;GV_EXIT:
  5908 000025B9 C3                  <1> 	retn
  5909                              <1> 
  5910                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  5911                              <1> hdc1_int: ; 21/02/2015
  5912                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  5913                              <1> ;								:
  5914                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  5915                              <1> ;								:
  5916                              <1> ;----------------------------------------------------------------
  5917                              <1> 
  5918                              <1> ; 22/12/2014
  5919                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  5920                              <1> ;	 '11/15/85'
  5921                              <1> ; AWARD BIOS 1999 (D1A0622) 
  5922                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  5923                              <1> 
  5924                              <1> ;int_76h:
  5925                              <1> HD_INT:
  5926                              <1> 	;push	ax
  5927                              <1> 	; 24/12/2021
  5928 000025BA 50                  <1> 	push	eax
  5929 000025BB 1E                  <1> 	push	ds
  5930                              <1> 	;CALL	DDS
  5931                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  5932 000025BC 66B81000            <1> 	mov	ax, KDATA
  5933 000025C0 8ED8                <1> 	mov 	ds, ax
  5934                              <1> 	;
  5935                              <1> 	;;MOV	@HF_INT_FLAG, 0FFH	; ALL DONE
  5936                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  5937 000025C2 C605[66650000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  5938                              <1> 	;
  5939                              <1> 	;push	dx
  5940                              <1> 	; 24/12/2021
  5941 000025C9 52                  <1> 	push	edx
  5942 000025CA 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  5943                              <1> 					; Clear Controller
  5944                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  5945 000025CE EC                  <1> 	in	al, dx			;
  5946                              <1> 	;pop	dx
  5947                              <1> 	; 24/12/2021
  5948 000025CF 5A                  <1> 	pop	edx
  5949                              <1> 	NEWIODELAY
  2165 000025D0 E6EB                <2>  out 0EBh,al
  5950                              <1> 	;
  5951 000025D2 B020                <1> 	mov	al, EOI			; NON-SPECIFIC END OF INTERRUPT
  5952 000025D4 E6A0                <1> 	out	INTB00, al		; FOR CONTROLLER #2
  5953                              <1> 	;JMP	$+2			; WAIT
  5954                              <1> 	NEWIODELAY
  2165 000025D6 E6EB                <2>  out 0EBh,al
  5955 000025D8 E620                <1> 	out	INTA00, al		; FOR CONTROLLER #1
  5956 000025DA 1F                  <1> 	pop	ds
  5957                              <1> 	;sti				; RE-ENABLE INTERRUPTS
  5958                              <1> 	;mov	ax, 9100h		; DEVICE POST
  5959                              <1> 	;int	15h			; INTERRUPT
  5960                              <1> irq15_iret: ; 25/02/2015
  5961                              <1> 	;pop	ax
  5962                              <1> 	; 24/12/2021
  5963 000025DB 58                  <1> 	pop	eax
  5964 000025DC CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  5965                              <1> 
  5966                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  5967                              <1> hdc2_int: ; 21/02/2015
  5968                              <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) ----------------------
  5969                              <1> ;								:
  5970                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  5971                              <1> ;								:
  5972                              <1> ;----------------------------------------------------------------
  5973                              <1> 
  5974                              <1> ;int_77h:
  5975                              <1> HD1_INT:
  5976                              <1> 	;push	ax
  5977                              <1> 	; 24/12/2021
  5978 000025DD 50                  <1> 	push	eax
  5979                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  5980                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  5981 000025DE B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  5982 000025E0 E6A0                <1> 	out	0A0h, al
  5983 000025E2 EB00                <1>         jmp short $+2
  5984 000025E4 EB00                <1> 	jmp short $+2
  5985 000025E6 E4A0                <1> 	in	al, 0A0h
  5986 000025E8 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  5987 000025EA 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  5988                              <1> 	;
  5989 000025EC 1E                  <1> 	push	ds
  5990                              <1> 	;CALL	DDS
  5991                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  5992 000025ED 66B81000            <1> 	mov	ax, KDATA
  5993 000025F1 8ED8                <1> 	mov 	ds, ax
  5994                              <1> 	;
  5995                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  5996                              <1>         ;or	byte [CS:HF_INT_FLAG], 0C0h 
  5997 000025F3 800D[66650000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  5998                              <1> 	;
  5999                              <1> 	;push	dx
  6000                              <1> 	; 24/12/2021
  6001 000025FA 52                  <1> 	push	edx
  6002 000025FB 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  6003                              <1> 					; Clear Controller (Award BIOS 1999)
  6004 000025FF EBCD                <1> 	jmp	short Clear_IRQ1415
  6005                              <1> 
  6006                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  6007                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  6008                              <1> 
  6009                              <1> ;////////////////////////////////////////////////////////////////////
  6010                              <1> ;; END OF DISK I/O SYTEM ///
  2102                                  %include 'memory.inc'  ; 09/03/2015
  2103                              <1> ; MEMORY.ASM - Retro UNIX 386 v1.1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2104                              <1> ; Retro UNIX 386 v1.1 Kernel (unix386.s, v0.2.1.1) - MEMORY.INC
  2105                              <1> ; Last Modification: 31/12/2021
  2106                              <1> ;
  2107                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2108                              <1> 
  2109                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2110                              <1> 
  2111                              <1> ;;04/11/2014 (unix386.s)	
  2112                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2113                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2114                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2115                              <1> ;;
  2116                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2117                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2118                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2119                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2120                              <1> 
  2121                              <1> ; 27/04/2015
  2122                              <1> ; 09/03/2015
  2123                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2124                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2125                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2126                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2127                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2128                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2129                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2130                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2131                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2132                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2133                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2134                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2135                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2136                              <1> SWP_DISK_READ_ERR 	   equ 40
  2137                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2138                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2139                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2140                              <1> SWP_DISK_WRITE_ERR         equ 44
  2141                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2142                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2143                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2144                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2145                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2146                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2147                              <1> 					; (Indicates that the page is not allocated
  2148                              <1> 					; for the process, it is a shared or system
  2149                              <1>                                         ; page, it must not be deallocated!)
  2150                              <1> ; 14/12/2020
  2151                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2152                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2153                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2154                              <1> 				; (Out of memory allocation table)	
  2155                              <1> ;
  2156                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2157                              <1> ;;
  2158                              <1> ;; 10/10/2014
  2159                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2160                              <1> ;;
  2161                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2162                              <1> ;;	(virtual address = physical address)
  2163                              <1> ;; KERNEL PAGE TABLES:
  2164                              <1> ;;	Kernel page directory and all page tables are
  2165                              <1> ;;	on memory as initialized, as equal to physical memory
  2166                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2167                              <1> ;;
  2168                              <1> ;;	what for: User pages may be swapped out, when accessing
  2169                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2170                              <1> ;;	kernel would have to swap it in! But it is also may be
  2171                              <1> ;;	in use by a user process. (In system/kernel mode
  2172                              <1> ;;	kernel can access all memory pages even if they are
  2173                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2174                              <1> ;;	cause conflicts.) 
  2175                              <1> ;;	
  2176                              <1> ;;	As result of these conditions,
  2177                              <1> ;;	all kernel pages must be initialized as equal to 
  2178                              <1> ;;	physical layout for preventing page faults. 
  2179                              <1> ;;	Also, calling "allocate page" procedure after
  2180                              <1> ;;	a page fault can cause another page fault (double fault)
  2181                              <1> ;;	if all kernel page tables would not be initialized.
  2182                              <1> ;;
  2183                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2184                              <1> ;;	memory allocation table. (double word aligned)
  2185                              <1> ;;
  2186                              <1> ;;	[next_page] = first/next free space to be searched
  2187                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2188                              <1> ;;
  2189                              <1> ;;	[last_page] = End of memory (users space), as offset
  2190                              <1> ;;	to memory allocation table. (double word aligned)
  2191                              <1> ;;
  2192                              <1> ;; USER PAGE TABLES:
  2193                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2194                              <1> ;;		'ready only' marked copies of the 
  2195                              <1> ;;		parent process's page table entries (for
  2196                              <1> ;;		same physical memory).
  2197                              <1> ;;		(A page will be copied to a new page after
  2198                              <1> ;;		 if it causes R/W page fault.)
  2199                              <1> ;;
  2200                              <1> ;;	Every user process has own (different)
  2201                              <1> ;;	page directory and page tables.	
  2202                              <1> ;;
  2203                              <1> ;;	Code starts at virtual address 0, always.
  2204                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2205                              <1> ;;	(Programs can be written/developed as simple
  2206                              <1> ;;	 flat memory programs.)
  2207                              <1> ;;
  2208                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2209                              <1> ;;	Memory page will be allocated by kernel only 
  2210                              <1> ;;		(in kernel/system mode only).
  2211                              <1> ;;	* After a
  2212                              <1> ;;	  - 'not present' page fault
  2213                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2214                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2215                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2216                              <1> ;;	  request by running process.
  2217                              <1> ;;	* While creating a process, allocating a new buffer,
  2218                              <1> ;;	  new page tables etc.
  2219                              <1> ;;
  2220                              <1> ;;	At first,
  2221                              <1> ;;	- 'allocate page' procedure will be called;
  2222                              <1> ;,	   if it will return with a valid (>0) physical address
  2223                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2224                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2225                              <1> ;;	- 'allocate page' will be called for allocating page
  2226                              <1> ;;	   directory, page table and running space (data/code).
  2227                              <1> ;;	- every successful 'allocate page' call will decrease
  2228                              <1> ;;	  'free_pages' count (pointer).
  2229                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2230                              <1> ;;	  if 'free_pages' points to a ZERO.
  2231                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2232                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2233                              <1> ;;	  error except errors caused by attribute conflicts.
  2234                              <1> ;;	 (swapper functions)	 
  2235                              <1> ;;					
  2236                              <1> ;;	At second,
  2237                              <1> ;;	- page directory entry will be updated then page table
  2238                              <1> ;;	  entry will be updated.		
  2239                              <1> ;;
  2240                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2241                              <1> ;;	- M.A.T. has a size according to available memory as
  2242                              <1> ;;	  follows:
  2243                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2244                              <1> ;;		  - a bit with value of 0 means allocated page
  2245                              <1> ;;		  - a bit with value of 1 means a free page
  2246                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2247                              <1> ;;	  depending on M.A.T.
  2248                              <1> ;;		(NOTE: Free page count will not be checked
  2249                              <1> ;;		again -on M.A.T.- after initialization. 
  2250                              <1> ;;		Kernel will trust on initial count.)
  2251                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2252                              <1> ;;	  and it will be increased by deallocation procedures.
  2253                              <1> ;;	
  2254                              <1> ;;	- Available memory will be calculated during
  2255                              <1> ;;	  the kernel's initialization stage (in real mode).
  2256                              <1> ;;	  Memory allocation table and kernel page tables 
  2257                              <1> ;;	  will be formatted/sized as result of available
  2258                              <1> ;;	  memory calculation before paging is enabled.
  2259                              <1> ;;
  2260                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2261                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2262                              <1> ;;	- Memory allocation for kernel page directory size 
  2263                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2264                              <1> ;;	  for page tables)
  2265                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2266                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2267                              <1> ;;	- User (available) space will be started 
  2268                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2269                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2270                              <1> ;;	  memory allocation table and kernel's page directory
  2271                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2272                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2273                              <1> ;; 	  for buffers.
  2274                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2275                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2276                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2277                              <1> ;;
  2278                              <1> ;; For 1GB Available Memory:
  2279                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2280                              <1> ;;	- Memory allocation for kernel page directory size 
  2281                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2282                              <1> ;;	  for page tables)
  2283                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2284                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2285                              <1> ;;	- User (available) space will be started 
  2286                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2287                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2288                              <1> ;;	  memory allocation table and kernel's page directory
  2289                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2290                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2291                              <1> ;; 	  for buffers.
  2292                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2293                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2294                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2295                              <1> ;;
  2296                              <1> ;;
  2297                              <1> 
  2298                              <1> ;;************************************************************************************
  2299                              <1> ;; 
  2300                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2301                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2302                              <1> 
  2303                              <1> ;; Main factor: "sys fork" system call 
  2304                              <1> ;;	
  2305                              <1> ;; 		FORK
  2306                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2307                              <1> ;;  writable pages ---->|
  2308                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2309                              <1> ;; 
  2310                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2311                              <1> ;; 
  2312                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2313                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2314                              <1> ;;       -while R/W bit is 0-. 
  2315                              <1> ;; 
  2316                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2317                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2318                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2319                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2320                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2321                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2322                              <1> ;; 
  2323                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2324                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2325                              <1> ;;   Parent's PTE attributes are not changed.
  2326                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2327                              <1> ;;    destroy/mix previous fork result).
  2328                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2329                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2330                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2331                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2332                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2333                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2334                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2335                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2336                              <1> ;; 
  2337                              <1> ;; !? WHAT FOR (duplication after duplication):
  2338                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2339                              <1> ;; program/executable code continues from specified location as child process, 
  2340                              <1> ;; returns back previous code location as parent process, every child after 
  2341                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2342                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2343                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2344                              <1> ;; was copied to child's process segment (all of code and data) according to
  2345                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2346                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2347                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2348                              <1> ;; (complete running image of parent process) to the child process; 
  2349                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2350                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2351                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2352                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2353                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2354                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2355                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2356                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2357                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2358                              <1> ;; for sharing same read only pages between parent and child processes.
  2359                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2360                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2361                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2362                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2363                              <1> ;; -deallocation problem-.
  2364                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2365                              <1> ;; 
  2366                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2367                              <1> ;; # Page fault handler will do those:
  2368                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2369                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2370                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2371                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2372                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2373                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2374                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2375                              <1> ;;     to child process.)	
  2376                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2377                              <1> ;; # Page fault handler will do those:
  2378                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2379                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2380                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2381                              <1> ;;     address or not. 
  2382                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2383                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2384                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2385                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2386                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2387                              <1> ;; 
  2388                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2389                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2390                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2391                              <1> ;;       duplication method details, it is not possible multiple child processes
  2392                              <1> ;;       were using same page with duplicated PTEs.
  2393                              <1> ;; 
  2394                              <1> ;;************************************************************************************   
  2395                              <1> 
  2396                              <1> ;; 08/10/2014
  2397                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2398                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2399                              <1> 
  2400                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2401                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2402                              <1> ;; (25/08/2014, Revision: 5057) file 
  2403                              <1> ;; by KolibriOS Team (2004-2012)
  2404                              <1> 
  2405                              <1> allocate_page:
  2406                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2407                              <1> 	; 01/07/2015
  2408                              <1> 	; 05/05/2015
  2409                              <1> 	; 30/04/2015
  2410                              <1> 	; 16/10/2014
  2411                              <1> 	; 08/10/2014
  2412                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2413                              <1> 	;
  2414                              <1> 	; INPUT -> none
  2415                              <1> 	;
  2416                              <1> 	; OUTPUT ->
  2417                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2418                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2419                              <1> 	;
  2420                              <1> 	;	CF = 1 and EAX = 0 
  2421                              <1> 	; 		   if there is not a free page to be allocated	
  2422                              <1> 	;
  2423                              <1> 	; Modified Registers -> none (except EAX)
  2424                              <1> 	;
  2425 00002601 A1[E0640000]        <1> 	mov	eax, [free_pages]
  2426 00002606 21C0                <1> 	and	eax, eax
  2427 00002608 7438                <1> 	jz	short out_of_memory
  2428                              <1> 	;
  2429 0000260A 53                  <1> 	push	ebx
  2430 0000260B 51                  <1> 	push	ecx
  2431                              <1> 	;
  2432 0000260C BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2433 00002611 89D9                <1> 	mov	ecx, ebx
  2434                              <1>  				     ; NOTE: 32 (first_page) is initial
  2435                              <1> 				     ; value of [next_page].
  2436                              <1> 				     ; It points to the first available
  2437                              <1> 				     ; page block for users (ring 3) ...	
  2438                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2439                              <1> 				     ; (at the of the first 4 MB)		
  2440 00002613 031D[E4640000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2441                              <1> 				 ; next_free_page >> 5
  2442 00002619 030D[E8640000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2443                              <1> 				 ; (total_pages - 1) >> 5
  2444                              <1> al_p_scan:
  2445 0000261F 39CB                <1> 	cmp	ebx, ecx
  2446 00002621 770A                <1> 	ja	short al_p_notfound
  2447                              <1> 	;
  2448                              <1> 	; 01/07/2015
  2449                              <1> 	; AMD64 Architecture Programmers Manual
  2450                              <1> 	; Volume 3:
  2451                              <1> 	; General-Purpose and System Instructions
  2452                              <1> 	;
  2453                              <1> 	; BSF - Bit Scan Forward
  2454                              <1> 	;
  2455                              <1> 	;   Searches the value in a register or a memory location
  2456                              <1> 	;   (second operand) for the least-significant set bit. 
  2457                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2458                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2459                              <1> 	;   register (first operand). If the second operand contains 0, 
  2460                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2461                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2462                              <1> 	;   of the searched value
  2463                              <1> 	;
  2464 00002623 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2465                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2466                              <1> 			   ; loads the destination with an index to
  2467                              <1> 			   ; first set bit. (0 -> 31) 
  2468                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2469 00002626 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2470                              <1> 			 ;
  2471                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2472                              <1> 			 ;	  with value of 1 means 
  2473                              <1> 			 ;	  the corresponding page is free 
  2474                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2475 00002628 83C304              <1> 	add	ebx, 4
  2476                              <1> 			 ; We return back for searching next page block
  2477                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2478                              <1> 			 ;	 we always will find at least 1 free page here.
  2479 0000262B EBF2                <1>         jmp     short al_p_scan
  2480                              <1> 	;
  2481                              <1> al_p_notfound:
  2482 0000262D 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2483 00002633 890D[E4640000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2484                              <1> 				 ; (deallocate_page procedure will change it)
  2485 00002639 31C0                <1> 	xor	eax, eax
  2486 0000263B A3[E0640000]        <1> 	mov	[free_pages], eax ; 0
  2487 00002640 59                  <1> 	pop	ecx
  2488 00002641 5B                  <1> 	pop	ebx
  2489                              <1> 	;
  2490                              <1> ; 24/12/2021
  2491                              <1> ; ('swap_out' procedure call is disabled)
  2492                              <1> 
  2493                              <1> out_of_memory:
  2494                              <1> ;	call	swap_out
  2495                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2496                              <1> ;	;
  2497                              <1> ;	sub 	eax, eax ; 0
  2498 00002642 F9                  <1> 	stc
  2499 00002643 C3                  <1> 	retn
  2500                              <1> 
  2501                              <1> al_p_found:
  2502 00002644 89D9                <1> 	mov	ecx, ebx
  2503 00002646 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2504 0000264C 890D[E4640000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2505                              <1> 				 ; address/offset (to the next)
  2506 00002652 FF0D[E0640000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2507                              <1> 	;
  2508 00002658 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2509                              <1> 				 ; is copied into the Carry Flag and then cleared
  2510                              <1> 				 ; in the destination.
  2511                              <1> 				 ;
  2512                              <1> 				 ; Reset the bit which is corresponding to the 
  2513                              <1> 				 ; (just) allocated page.
  2514                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2515 0000265B C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2516 0000265E 01C8                <1> 	add	eax, ecx	 ; = page number
  2517 00002660 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2518                              <1> 	; EAX = physical address of memory page
  2519                              <1> 	;
  2520                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2521                              <1> 	;       according to this EAX value...
  2522 00002663 59                  <1> 	pop	ecx
  2523 00002664 5B                  <1> 	pop	ebx
  2524                              <1> al_p_ok:
  2525 00002665 C3                  <1> 	retn
  2526                              <1> 
  2527                              <1> make_page_dir:
  2528                              <1> 	; 18/04/2015
  2529                              <1> 	; 12/04/2015
  2530                              <1> 	; 23/10/2014
  2531                              <1> 	; 16/10/2014
  2532                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2533                              <1> 	;
  2534                              <1> 	; INPUT ->
  2535                              <1> 	;	none
  2536                              <1> 	; OUTPUT ->
  2537                              <1> 	;	(EAX = 0)
  2538                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2539                              <1> 	;	cf = 0 ->
  2540                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2541                              <1> 	;		  process/user.
  2542                              <1> 	;
  2543                              <1> 	; Modified Registers -> EAX
  2544                              <1> 	;
  2545 00002666 E896FFFFFF          <1> 	call	allocate_page
  2546 0000266B 7216                <1> 	jc	short mkpd_error
  2547                              <1> 	;
  2548 0000266D A3[F1680000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2549                              <1> 				  ; (Physical address)
  2550                              <1> clear_page:
  2551                              <1> 	; 18/04/2015
  2552                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2553                              <1> 	;
  2554                              <1> 	; INPUT ->
  2555                              <1> 	;	EAX = physical address of the page
  2556                              <1> 	; OUTPUT ->
  2557                              <1> 	;	all bytes of the page will be cleared
  2558                              <1> 	;
  2559                              <1> 	; Modified Registers -> none
  2560                              <1> 	;
  2561 00002672 57                  <1> 	push	edi
  2562 00002673 51                  <1> 	push	ecx
  2563 00002674 50                  <1> 	push	eax
  2564 00002675 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2565 0000267A 89C7                <1> 	mov	edi, eax
  2566 0000267C 31C0                <1> 	xor	eax, eax
  2567 0000267E F3AB                <1> 	rep	stosd
  2568 00002680 58                  <1> 	pop	eax
  2569 00002681 59                  <1> 	pop	ecx
  2570 00002682 5F                  <1> 	pop	edi
  2571                              <1> mkpd_error:
  2572                              <1> mkpt_error:
  2573 00002683 C3                  <1> 	retn
  2574                              <1> 
  2575                              <1> make_page_table:
  2576                              <1> 	; 23/06/2015
  2577                              <1> 	; 18/04/2015
  2578                              <1> 	; 12/04/2015
  2579                              <1> 	; 16/10/2014
  2580                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2581                              <1> 	;
  2582                              <1> 	; INPUT ->
  2583                              <1> 	;	EBX = virtual (linear) address
  2584                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2585                              <1> 	;	      (higher 20 bits must be ZERO)
  2586                              <1> 	;	      (bit 0 must be 1)	 
  2587                              <1> 	;	u.pgdir = page directory (physical) address
  2588                              <1> 	; OUTPUT ->
  2589                              <1> 	;	EDX = Page directory entry address
  2590                              <1> 	;	EAX = Page table address
  2591                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2592                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2593                              <1> 	;
  2594                              <1> 	; Modified Registers -> EAX, EDX
  2595                              <1> 	;
  2596 00002684 E878FFFFFF          <1> 	call	allocate_page
  2597 00002689 72F8                <1> 	jc	short mkpt_error
  2598 0000268B E811000000          <1> 	call	set_pde	
  2599 00002690 EBE0                <1> 	jmp	short clear_page
  2600                              <1> 
  2601                              <1> make_page:
  2602                              <1> 	; 24/07/2015
  2603                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2604                              <1> 	;
  2605                              <1> 	; INPUT ->
  2606                              <1> 	;	EBX = virtual (linear) address
  2607                              <1> 	;	ECX = page attributes (lower 12 bits)
  2608                              <1> 	;	      (higher 20 bits must be ZERO)
  2609                              <1> 	;	      (bit 0 must be 1)	 
  2610                              <1> 	;	u.pgdir = page directory (physical) address
  2611                              <1> 	; OUTPUT ->
  2612                              <1> 	;	EBX = Virtual address
  2613                              <1> 	;	(EDX = PTE value)
  2614                              <1> 	;	EAX = Physical address
  2615                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2616                              <1> 	;
  2617                              <1> 	; Modified Registers -> EAX, EDX
  2618                              <1> 	;
  2619 00002692 E86AFFFFFF          <1> 	call	allocate_page
  2620 00002697 7207                <1> 	jc	short mkp_err
  2621 00002699 E821000000          <1> 	call	set_pte	
  2622 0000269E 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2623                              <1> mkp_err:
  2624 000026A0 C3                  <1> 	retn
  2625                              <1> 
  2626                              <1> set_pde:	; Set page directory entry (PDE)
  2627                              <1> 	; 20/07/2015
  2628                              <1> 	; 18/04/2015
  2629                              <1> 	; 12/04/2015
  2630                              <1> 	; 23/10/2014
  2631                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2632                              <1> 	;
  2633                              <1> 	; INPUT ->
  2634                              <1> 	;	EAX = physical address
  2635                              <1> 	;	      (use present value if EAX = 0)
  2636                              <1> 	;	EBX = virtual (linear) address
  2637                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2638                              <1> 	;	      (higher 20 bits must be ZERO)
  2639                              <1> 	;	      (bit 0 must be 1)	 
  2640                              <1> 	;	u.pgdir = page directory (physical) address
  2641                              <1> 	; OUTPUT ->
  2642                              <1> 	;	EDX = PDE address
  2643                              <1> 	;	EAX = page table address (physical)
  2644                              <1> 	;	;(CF=1 -> Invalid page address)
  2645                              <1> 	;
  2646                              <1> 	; Modified Registers -> EDX
  2647                              <1> 	;
  2648 000026A1 89DA                <1> 	mov	edx, ebx
  2649 000026A3 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2650 000026A6 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2651 000026A9 0315[F1680000]      <1> 	add	edx, [u.pgdir]
  2652                              <1> 	;
  2653 000026AF 21C0                <1> 	and	eax, eax
  2654 000026B1 7506                <1> 	jnz	short spde_1
  2655                              <1> 	;
  2656 000026B3 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2657                              <1> 	;test	al, 1
  2658                              <1> 	;jz	short spde_2
  2659 000026B5 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2660                              <1> spde_1:
  2661                              <1> 	;and	cx, 0FFFh
  2662 000026B9 8902                <1> 	mov	[edx], eax
  2663 000026BB 66090A              <1> 	or	[edx], cx
  2664 000026BE C3                  <1> 	retn
  2665                              <1> ;spde_2: ; error
  2666                              <1> ;	stc
  2667                              <1> ;	retn
  2668                              <1> 
  2669                              <1> set_pte:	; Set page table entry (PTE)
  2670                              <1> 	; 24/07/2015
  2671                              <1> 	; 20/07/2015
  2672                              <1> 	; 23/06/2015
  2673                              <1> 	; 18/04/2015
  2674                              <1> 	; 12/04/2015
  2675                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2676                              <1> 	;
  2677                              <1> 	; INPUT ->
  2678                              <1> 	;	EAX = physical page address
  2679                              <1> 	;	      (use present value if EAX = 0)
  2680                              <1> 	;	EBX = virtual (linear) address
  2681                              <1> 	;	ECX = page attributes (lower 12 bits)
  2682                              <1> 	;	      (higher 20 bits must be ZERO)
  2683                              <1> 	;	      (bit 0 must be 1)	 
  2684                              <1> 	;	u.pgdir = page directory (physical) address
  2685                              <1> 	; OUTPUT ->
  2686                              <1> 	;	EAX = physical page address
  2687                              <1> 	;	(EDX = PTE value)
  2688                              <1> 	;	EBX = virtual address
  2689                              <1> 	;
  2690                              <1> 	;	CF = 1 -> error
  2691                              <1> 	;
  2692                              <1> 	; Modified Registers -> EAX, EDX
  2693                              <1> 	;
  2694 000026BF 50                  <1> 	push	eax
  2695 000026C0 A1[F1680000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2696 000026C5 E837000000          <1> 	call 	get_pde
  2697                              <1> 		; EDX = PDE address
  2698                              <1> 		; EAX = PDE value
  2699 000026CA 5A                  <1> 	pop	edx ; physical page address
  2700 000026CB 722A                <1> 	jc	short spte_err ; PDE not present
  2701                              <1> 	;
  2702 000026CD 53                  <1> 	push	ebx ; 24/07/2015
  2703 000026CE 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2704                              <1> 			    ; EDX = PT address (physical)	
  2705 000026D2 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2706 000026D5 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2707                              <1> 			 ; clear higher 10 bits (PD bits)
  2708 000026DB C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2709 000026DE 01C3                <1> 	add	ebx, eax
  2710                              <1> 	;
  2711 000026E0 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2712 000026E2 A801                <1> 	test	al, 1
  2713 000026E4 740C                <1> 	jz	short spte_0
  2714 000026E6 09D2                <1> 	or	edx, edx
  2715 000026E8 750F                <1> 	jnz	short spte_1
  2716 000026EA 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2717 000026EE 89C2                <1> 	mov	edx, eax
  2718 000026F0 EB09                <1> 	jmp	short spte_2	
  2719                              <1> spte_0:
  2720                              <1> 	; If this PTE contains a swap (disk) address,
  2721                              <1> 	; it can be updated by using 'swap_in' procedure
  2722                              <1> 	; only!
  2723 000026F2 21C0                <1> 	and	eax, eax
  2724 000026F4 7403                <1> 	jz	short spte_1
  2725                              <1> 	; 24/07/2015
  2726                              <1> 	; swapped page ! (on disk)
  2727 000026F6 5B                  <1> 	pop	ebx
  2728                              <1> spte_err:
  2729 000026F7 F9                  <1> 	stc
  2730 000026F8 C3                  <1> 	retn
  2731                              <1> spte_1: 
  2732 000026F9 89D0                <1> 	mov	eax, edx
  2733                              <1> spte_2:
  2734 000026FB 09CA                <1> 	or	edx, ecx
  2735                              <1> 	; 23/06/2015
  2736 000026FD 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2737                              <1> 	; 24/07/2015
  2738 000026FF 5B                  <1> 	pop	ebx
  2739 00002700 C3                  <1> 	retn
  2740                              <1> 
  2741                              <1> get_pde:	; Get present value of the relevant PDE
  2742                              <1> 	; 20/07/2015
  2743                              <1> 	; 18/04/2015
  2744                              <1> 	; 12/04/2015
  2745                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2746                              <1> 	;
  2747                              <1> 	; INPUT ->
  2748                              <1> 	;	EBX = virtual (linear) address
  2749                              <1> 	;	EAX = page directory (physical) address
  2750                              <1> 	; OUTPUT ->
  2751                              <1> 	;	EDX = Page directory entry address
  2752                              <1> 	;	EAX = Page directory entry value
  2753                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2754                              <1> 	; Modified Registers -> EDX, EAX
  2755                              <1> 	;
  2756 00002701 89DA                <1> 	mov	edx, ebx
  2757 00002703 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2758 00002706 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2759 00002709 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2760 0000270B 8B02                <1> 	mov	eax, [edx]
  2761 0000270D A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2762 0000270F 751F                <1> 	jnz	short gpte_retn
  2763 00002711 F9                  <1> 	stc
  2764                              <1> gpde_retn:	
  2765 00002712 C3                  <1> 	retn
  2766                              <1> 
  2767                              <1> get_pte:
  2768                              <1> 		; Get present value of the relevant PTE
  2769                              <1> 	; 29/07/2015
  2770                              <1> 	; 20/07/2015
  2771                              <1> 	; 18/04/2015
  2772                              <1> 	; 12/04/2015
  2773                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2774                              <1> 	;
  2775                              <1> 	; INPUT ->
  2776                              <1> 	;	EBX = virtual (linear) address
  2777                              <1> 	;	EAX = page directory (physical) address
  2778                              <1> 	; OUTPUT ->
  2779                              <1> 	;	EDX = Page table entry address (if CF=0)
  2780                              <1> 	;	      Page directory entry address (if CF=1)
  2781                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2782                              <1> 	;	EAX = Page table entry value (page address)
  2783                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2784                              <1> 	; Modified Registers -> EAX, EDX
  2785                              <1> 	;
  2786 00002713 E8E9FFFFFF          <1> 	call 	get_pde
  2787 00002718 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2788                              <1> 	;jnc	short gpte_1
  2789                              <1> 	;retn
  2790                              <1> ;gpte_1:
  2791 0000271A 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2792 0000271E 89DA                <1> 	mov	edx, ebx
  2793 00002720 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2794 00002723 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2795                              <1> 			 ; clear higher 10 bits (PD bits)
  2796 00002729 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2797 0000272C 01C2                <1> 	add	edx, eax
  2798 0000272E 8B02                <1> 	mov	eax, [edx]
  2799                              <1> gpte_retn:
  2800 00002730 C3                  <1> 	retn
  2801                              <1> 
  2802                              <1> deallocate_page_dir:
  2803                              <1> 	; 15/09/2015
  2804                              <1> 	; 05/08/2015
  2805                              <1> 	; 30/04/2015
  2806                              <1> 	; 28/04/2015
  2807                              <1> 	; 17/10/2014
  2808                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2809                              <1> 	;
  2810                              <1> 	; INPUT ->
  2811                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2812                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2813                              <1> 	; OUTPUT ->
  2814                              <1> 	;	All of page tables in the page directory
  2815                              <1> 	;	and page dir's itself will be deallocated
  2816                              <1> 	;	except 'read only' duplicated pages (will be converted
  2817                              <1> 	;	to writable pages).
  2818                              <1> 	;
  2819                              <1> 	; Modified Registers -> EAX
  2820                              <1> 	;
  2821                              <1> 	;
  2822 00002731 56                  <1> 	push	esi
  2823 00002732 51                  <1> 	push	ecx
  2824 00002733 50                  <1> 	push	eax
  2825 00002734 89C6                <1> 	mov	esi, eax 
  2826 00002736 31C9                <1> 	xor	ecx, ecx
  2827                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2828                              <1> 	; it must not be deallocated
  2829 00002738 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2830                              <1> dapd_0:
  2831 0000273A AD                  <1> 	lodsd
  2832 0000273B A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2833 0000273D 7409                <1> 	jz	short dapd_1	
  2834 0000273F 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2835 00002743 E812000000          <1> 	call	deallocate_page_table			
  2836                              <1> dapd_1:
  2837 00002748 41                  <1> 	inc	ecx ; page directory entry index
  2838 00002749 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2839 0000274F 72E9                <1> 	jb	short dapd_0
  2840                              <1> dapd_2:
  2841 00002751 58                  <1> 	pop	eax
  2842 00002752 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2843 00002757 59                  <1> 	pop	ecx
  2844 00002758 5E                  <1> 	pop	esi
  2845 00002759 C3                  <1> 	retn
  2846                              <1> 
  2847                              <1> deallocate_page_table:
  2848                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2849                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2850                              <1> 	; 19/09/2015
  2851                              <1> 	; 15/09/2015
  2852                              <1> 	; 05/08/2015
  2853                              <1> 	; 30/04/2015
  2854                              <1> 	; 28/04/2015
  2855                              <1> 	; 24/10/2014
  2856                              <1> 	; 23/10/2014
  2857                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2858                              <1> 	;
  2859                              <1> 	; INPUT ->
  2860                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2861                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2862                              <1> 	;	(ECX = page directory entry index)
  2863                              <1> 	; OUTPUT ->
  2864                              <1> 	;	All of pages in the page table and page table's itself
  2865                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2866                              <1> 	;	(will be converted to writable pages).
  2867                              <1> 	;
  2868                              <1> 	; Modified Registers -> EAX
  2869                              <1> 	;
  2870 0000275A 56                  <1> 	push	esi
  2871 0000275B 57                  <1> 	push	edi
  2872 0000275C 52                  <1> 	push	edx
  2873 0000275D 50                  <1> 	push	eax ; *
  2874 0000275E 89C6                <1> 	mov	esi, eax 
  2875 00002760 31FF                <1> 	xor	edi, edi ; 0
  2876                              <1> dapt_0:
  2877 00002762 AD                  <1> 	lodsd
  2878 00002763 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2879 00002765 7455                <1> 	jz	short dapt_1
  2880                              <1> 	;
  2881 00002767 A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2882                              <1> 				  ; (must be 1)
  2883 00002769 753F                <1> 	jnz	short dapt_3
  2884                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2885 0000276B 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2886                              <1> 				   ; as child's page ?
  2887 0000276F 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2888                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2889                              <1> 	; ECX = page directory entry index (0-1023)
  2890 00002771 53                  <1> 	push	ebx
  2891 00002772 51                  <1> 	push	ecx
  2892 00002773 66C1E102            <1> 	shl	cx, 2 ; *4 
  2893 00002777 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2894 00002779 8B0B                <1> 	mov	ecx, [ebx]
  2895 0000277B F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2896 0000277E 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2897 00002780 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2898                              <1> 	; EDI = page table entry index (0-1023)
  2899 00002785 89FA                <1> 	mov	edx, edi 
  2900 00002787 66C1E202            <1> 	shl	dx, 2 ; *4 
  2901 0000278B 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2902 0000278D 8B1A                <1> 	mov	ebx, [edx]
  2903 0000278F F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2904 00002792 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2905 00002794 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2906 00002798 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2907 0000279D 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2908 0000279F 7507                <1> 	jne	short dapt_2	; not same page
  2909                              <1> 				; deallocate the child's page
  2910 000027A1 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2911 000027A4 59                  <1> 	pop	ecx
  2912 000027A5 5B                  <1> 	pop	ebx
  2913 000027A6 EB0D                <1> 	jmp	short dapt_4
  2914                              <1> 
  2915                              <1> ; 24/12/2021
  2916                              <1> ; ('dapt_1' is disabled)
  2917                              <1> ;
  2918                              <1> ;dapt_1:
  2919                              <1> ;	or	eax, eax	; swapped page ?
  2920                              <1> ;	jz	short dapt_5	; no
  2921                              <1> ;				; yes
  2922                              <1> ;	shr	eax, 1
  2923                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2924                              <1> ;				  ; on the swap disk (or in file)
  2925                              <1> ;	jmp	short dapt_5
  2926                              <1> dapt_2:
  2927 000027A8 59                  <1> 	pop	ecx
  2928 000027A9 5B                  <1> 	pop	ebx
  2929                              <1> dapt_3:	
  2930                              <1> 	; 12/07/2016
  2931 000027AA 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2932 000027AE 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2933                              <1> 	;
  2934                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2935 000027B0 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2936                              <1> dapt_4:
  2937 000027B5 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2938                              <1> dapt_1:	; 24/12/2021
  2939                              <1> dapt_5:
  2940 000027BC 47                  <1> 	inc	edi ; page table entry index
  2941 000027BD 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2942 000027C3 729D                <1> 	jb	short dapt_0
  2943                              <1> 	;
  2944 000027C5 58                  <1> 	pop	eax ; *
  2945 000027C6 5A                  <1> 	pop	edx
  2946 000027C7 5F                  <1> 	pop	edi	
  2947 000027C8 5E                  <1> 	pop	esi
  2948                              <1> 	;
  2949                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2950                              <1> 	;retn
  2951                              <1> 
  2952                              <1> deallocate_page:
  2953                              <1> 	; 15/09/2015
  2954                              <1> 	; 28/04/2015
  2955                              <1> 	; 10/03/2015
  2956                              <1> 	; 17/10/2014
  2957                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2958                              <1> 	;
  2959                              <1> 	; INPUT -> 
  2960                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2961                              <1> 	; OUTPUT ->
  2962                              <1> 	;	[free_pages] is increased
  2963                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2964                              <1> 	;	CF = 1 if the page is already deallocated
  2965                              <1> 	; 	       (or not allocated) before.  
  2966                              <1> 	;
  2967                              <1> 	; Modified Registers -> EAX
  2968                              <1> 	;
  2969 000027C9 53                  <1> 	push	ebx
  2970 000027CA 52                  <1> 	push	edx
  2971                              <1> 	;
  2972 000027CB C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2973                              <1> 				     ; 12 bits right
  2974                              <1> 				     ; to get page number
  2975 000027CE 89C2                <1> 	mov	edx, eax
  2976                              <1> 	; 15/09/2015
  2977 000027D0 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2978                              <1> 				     ; (1 allocation bit = 1 page)
  2979                              <1> 				     ; (1 allocation bytes = 8 pages)
  2980 000027D3 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2981                              <1> 				     ; (to get 32 bit position)			
  2982                              <1> 	;
  2983 000027D6 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2984 000027DB 01D3                <1> 	add	ebx, edx
  2985 000027DD 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2986                              <1> 				     ; (allocation bit position)	 
  2987 000027E0 3B15[E4640000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2988                              <1> 				     ; than the address in 'next_page' ?
  2989                              <1> 				     ; (next/first free page value)		
  2990 000027E6 7306                <1> 	jnb	short dap_1	     ; no	
  2991 000027E8 8915[E4640000]      <1> 	mov	[next_page], edx     ; yes
  2992                              <1> dap_1:
  2993 000027EE 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2994                              <1> 				     ; set relevant bit to 1.
  2995                              <1> 				     ; set CF to the previous bit value	
  2996                              <1> 	;cmc			     ; complement carry flag	
  2997                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2998                              <1> 				     ; if the page is already deallocated
  2999                              <1> 				     ; before.	
  3000 000027F1 FF05[E0640000]      <1>         inc     dword [free_pages]
  3001                              <1> dap_2:
  3002 000027F7 5A                  <1> 	pop	edx
  3003 000027F8 5B                  <1> 	pop	ebx
  3004 000027F9 C3                  <1> 	retn
  3005                              <1> 
  3006                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3007                              <1> ;;                                                              ;;
  3008                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  3009                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  3010                              <1> ;;                                                              ;;
  3011                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3012                              <1> 
  3013                              <1> ;;$Revision: 5057 $
  3014                              <1> 
  3015                              <1> 
  3016                              <1> ;;align 4
  3017                              <1> ;;proc alloc_page
  3018                              <1> 
  3019                              <1> ;;        pushfd
  3020                              <1> ;;        cli
  3021                              <1> ;;        push    ebx
  3022                              <1> ;;;//-
  3023                              <1> ;;        cmp     [pg_data.pages_free], 1
  3024                              <1> ;;        jle     .out_of_memory
  3025                              <1> ;;;//-
  3026                              <1> ;;
  3027                              <1> ;;        mov     ebx, [page_start]
  3028                              <1> ;;        mov     ecx, [page_end]
  3029                              <1> ;;.l1:
  3030                              <1> ;;        bsf     eax, [ebx];
  3031                              <1> ;;        jnz     .found
  3032                              <1> ;;        add     ebx, 4
  3033                              <1> ;;        cmp     ebx, ecx
  3034                              <1> ;;        jb      .l1
  3035                              <1> ;;        pop     ebx
  3036                              <1> ;;        popfd
  3037                              <1> ;;        xor     eax, eax
  3038                              <1> ;;        ret
  3039                              <1> ;;.found:
  3040                              <1> ;;;//-
  3041                              <1> ;;        dec     [pg_data.pages_free]
  3042                              <1> ;;        jz      .out_of_memory
  3043                              <1> ;;;//-
  3044                              <1> ;;        btr     [ebx], eax
  3045                              <1> ;;        mov     [page_start], ebx
  3046                              <1> ;;        sub     ebx, sys_pgmap
  3047                              <1> ;;        lea     eax, [eax+ebx*8]
  3048                              <1> ;;        shl     eax, 12
  3049                              <1> ;;;//-       dec [pg_data.pages_free]
  3050                              <1> ;;        pop     ebx
  3051                              <1> ;;        popfd
  3052                              <1> ;;        ret
  3053                              <1> ;;;//-
  3054                              <1> ;;.out_of_memory:
  3055                              <1> ;;        mov     [pg_data.pages_free], 1
  3056                              <1> ;;        xor     eax, eax
  3057                              <1> ;;        pop     ebx
  3058                              <1> ;;        popfd
  3059                              <1> ;;        ret
  3060                              <1> ;;;//-
  3061                              <1> ;;endp
  3062                              <1> 
  3063                              <1> duplicate_page_dir:
  3064                              <1> 	; 21/09/2015
  3065                              <1> 	; 31/08/2015
  3066                              <1> 	; 20/07/2015
  3067                              <1> 	; 28/04/2015
  3068                              <1> 	; 27/04/2015
  3069                              <1> 	; 18/04/2015
  3070                              <1> 	; 12/04/2015
  3071                              <1> 	; 18/10/2014
  3072                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3073                              <1> 	;
  3074                              <1> 	; INPUT -> 
  3075                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3076                              <1> 	;		    page directory.
  3077                              <1> 	; OUTPUT ->
  3078                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3079                              <1> 	;	       page directory.
  3080                              <1> 	;	(New page directory with new page table entries.)
  3081                              <1> 	;	(New page tables with read only copies of the parent's
  3082                              <1> 	;	pages.)
  3083                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3084                              <1> 	;
  3085                              <1> 	; Modified Registers -> none (except EAX)
  3086                              <1> 	;
  3087 000027FA E802FEFFFF          <1> 	call	allocate_page
  3088 000027FF 723E                <1> 	jc	short dpd_err
  3089                              <1> 	;
  3090 00002801 55                  <1> 	push	ebp ; 20/07/2015
  3091 00002802 56                  <1> 	push	esi
  3092 00002803 57                  <1> 	push	edi
  3093 00002804 53                  <1> 	push	ebx
  3094 00002805 51                  <1> 	push	ecx
  3095 00002806 8B35[F1680000]      <1> 	mov	esi, [u.pgdir]
  3096 0000280C 89C7                <1> 	mov	edi, eax
  3097 0000280E 50                  <1> 	push	eax ; save child's page directory address
  3098                              <1> 	; 31/08/2015
  3099                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3100                              <1> 	; (use same system space for all user page tables) 
  3101 0000280F A5                  <1> 	movsd
  3102 00002810 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3103 00002815 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3104                              <1> dpd_0:	
  3105 0000281A AD                  <1> 	lodsd
  3106                              <1> 	;or	eax, eax
  3107                              <1>         ;jnz     short dpd_1
  3108 0000281B A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3109 0000281D 7508                <1> 	jnz	short dpd_1
  3110                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3111 0000281F 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3112 00002825 EB0F                <1> 	jmp	short dpd_2
  3113                              <1> dpd_1:	
  3114 00002827 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3115 0000282B 89C3                <1> 	mov	ebx, eax
  3116                              <1> 	; EBX = Parent's page table address
  3117 0000282D E81F000000          <1> 	call	duplicate_page_table
  3118 00002832 720C                <1> 	jc	short dpd_p_err
  3119                              <1> 	; EAX = Child's page table address
  3120 00002834 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3121                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3122                              <1> 			 ; (present, writable, user)
  3123                              <1> dpd_2:
  3124 00002836 AB                  <1> 	stosd
  3125 00002837 E2E1                <1> 	loop	dpd_0
  3126                              <1> 	;
  3127 00002839 58                  <1> 	pop	eax  ; restore child's page directory address
  3128                              <1> dpd_3:
  3129 0000283A 59                  <1> 	pop	ecx
  3130 0000283B 5B                  <1> 	pop	ebx
  3131 0000283C 5F                  <1> 	pop	edi
  3132 0000283D 5E                  <1> 	pop	esi
  3133 0000283E 5D                  <1> 	pop	ebp ; 20/07/2015
  3134                              <1> dpd_err:
  3135 0000283F C3                  <1> 	retn
  3136                              <1> dpd_p_err:
  3137                              <1> 	; release the allocated pages missing (recover free space)
  3138 00002840 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3139 00002841 8B1D[F1680000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3140 00002847 E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3141 0000284C 29C0                <1> 	sub	eax, eax ; 0
  3142 0000284E F9                  <1> 	stc
  3143 0000284F EBE9                <1> 	jmp	short dpd_3	
  3144                              <1> 
  3145                              <1> duplicate_page_table:
  3146                              <1> 	; 31/12/2021
  3147                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3148                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3149                              <1> 	; 21/09/2015
  3150                              <1> 	; 20/07/2015
  3151                              <1> 	; 05/05/2015
  3152                              <1> 	; 28/04/2015
  3153                              <1> 	; 27/04/2015
  3154                              <1> 	; 18/04/2015
  3155                              <1> 	; 18/10/2014
  3156                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3157                              <1> 	;
  3158                              <1> 	; INPUT -> 
  3159                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3160                              <1> 	;       20/02/2017		 
  3161                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3162                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3163                              <1> 	; OUTPUT ->
  3164                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3165                              <1> 	;	      (with 'read only' attribute of page table entries)
  3166                              <1> 	;	20/02/2017
  3167                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3168                              <1> 	;	
  3169                              <1> 	;	CF = 1 -> error 
  3170                              <1> 	;
  3171                              <1> 	; Modified Registers -> EBP (except EAX)
  3172                              <1> 	;
  3173 00002851 E8ABFDFFFF          <1> 	call	allocate_page
  3174 00002856 725B                <1> 	jc	short dpt_err
  3175                              <1> 	;
  3176 00002858 50                  <1> 	push	eax ; *
  3177 00002859 56                  <1> 	push	esi
  3178 0000285A 57                  <1> 	push	edi
  3179 0000285B 52                  <1> 	push	edx
  3180 0000285C 51                  <1> 	push	ecx
  3181                              <1> 	;
  3182 0000285D 89DE                <1> 	mov	esi, ebx
  3183 0000285F 89C7                <1> 	mov	edi, eax
  3184 00002861 89C2                <1> 	mov	edx, eax
  3185 00002863 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3186                              <1> dpt_0:
  3187 00002869 AD                  <1> 	lodsd
  3188 0000286A 21C0                <1> 	and	eax, eax
  3189 0000286C 7435                <1> 	jz	short dpt_3
  3190 0000286E A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3191                              <1> 	; 24/12/2021
  3192 00002870 7503                <1> 	jnz	short dpt_1
  3193                              <1> 	;jz	short dpt_p_err
  3194                              <1> 	; 31/12/2021
  3195 00002872 F9                  <1> 	stc
  3196 00002873 EB39                <1> 	jmp	short dpt_p_err
  3197                              <1> 
  3198                              <1> ; 24/12/2021
  3199                              <1> ; ('reload_page' procedure call is disabled)
  3200                              <1> ;
  3201                              <1> ;	; 20/07/2015
  3202                              <1> ;	; ebp = virtual (linear) address of the memory page
  3203                              <1> ;	call	reload_page ; 28/04/2015
  3204                              <1> ;	jc	short dpt_p_err
  3205                              <1> dpt_1:
  3206                              <1> 	; 21/09/2015
  3207 00002875 89C1                <1> 	mov	ecx, eax
  3208 00002877 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3209 0000287B F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3210 0000287E 751A                <1> 	jnz	short dpt_2
  3211                              <1> 	; Read only (parent) page
  3212                              <1> 	; 	- there is a third process which uses this page -
  3213                              <1> 	; Allocate a new page for the child process
  3214 00002880 E87CFDFFFF          <1> 	call	allocate_page
  3215 00002885 7227                <1> 	jc	short dpt_p_err
  3216 00002887 57                  <1> 	push	edi
  3217 00002888 56                  <1> 	push	esi
  3218 00002889 89CE                <1> 	mov	esi, ecx
  3219 0000288B 89C7                <1> 	mov	edi, eax
  3220 0000288D B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3221 00002892 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3222 00002894 5E                  <1> 	pop	esi
  3223 00002895 5F                  <1> 	pop	edi
  3224                              <1> 	;
  3225                              <1> 
  3226                              <1> ; 24/12/2021
  3227                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3228                              <1> ; 
  3229                              <1> ;	push	ebx
  3230                              <1> ;	push	eax
  3231                              <1> ;	; 20/07/2015
  3232                              <1> ;	mov	ebx, ebp
  3233                              <1> ;	; ebx = virtual (linear) address of the memory page
  3234                              <1> ;	call	add_to_swap_queue
  3235                              <1> ;	pop	eax
  3236                              <1> ;	pop	ebx
  3237                              <1> 
  3238                              <1> 	; 21/09/2015
  3239 00002896 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3240                              <1> 		; user + writable + present page
  3241 00002898 EB09                <1> 	jmp	short dpt_3
  3242                              <1> dpt_2:
  3243                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3244 0000289A 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3245                              <1> 		    ; (read only page!)
  3246 0000289C 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3247 0000289F 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3248                              <1> dpt_3:
  3249 000028A3 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3250                              <1> 	;
  3251 000028A4 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3252                              <1> 	;
  3253 000028AA 39D7                <1> 	cmp	edi, edx
  3254 000028AC 72BB                <1> 	jb	short dpt_0
  3255                              <1> dpt_p_err:
  3256 000028AE 59                  <1> 	pop	ecx
  3257 000028AF 5A                  <1> 	pop	edx
  3258 000028B0 5F                  <1> 	pop	edi
  3259 000028B1 5E                  <1> 	pop	esi
  3260 000028B2 58                  <1> 	pop	eax ; *
  3261                              <1> dpt_err:
  3262 000028B3 C3                  <1> 	retn
  3263                              <1> 
  3264                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3265                              <1> 	; 31/12/2021
  3266                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3267                              <1> 	; 21/09/2015
  3268                              <1> 	; 19/09/2015
  3269                              <1> 	; 17/09/2015
  3270                              <1> 	; 28/08/2015
  3271                              <1> 	; 20/07/2015
  3272                              <1> 	; 28/06/2015
  3273                              <1> 	; 03/05/2015
  3274                              <1> 	; 30/04/2015
  3275                              <1> 	; 18/04/2015
  3276                              <1> 	; 12/04/2015
  3277                              <1> 	; 30/10/2014
  3278                              <1> 	; 11/09/2014
  3279                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3280                              <1> 	;
  3281                              <1> 	; Note: This is not an interrupt/exception handler.
  3282                              <1> 	;	This is a 'page fault remedy' subroutine 
  3283                              <1> 	;	which will be called by standard/uniform
  3284                              <1> 	;	exception handler.
  3285                              <1> 	;
  3286                              <1> 	; INPUT -> 
  3287                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3288                              <1> 	;
  3289                              <1> 	;	cr2 = the virtual (linear) address 
  3290                              <1> 	;	      which has caused to page fault (19/09/2015)
  3291                              <1> 	;
  3292                              <1> 	; OUTPUT ->
  3293                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3294                              <1> 	;	EAX = 0 -> no error
  3295                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3296                              <1> 	;
  3297                              <1> 	; Modified Registers -> none (except EAX)
  3298                              <1> 	;	
  3299                              <1>         ;
  3300                              <1>         ; ERROR CODE:
  3301                              <1> 	;	 31  .....	4   3	2   1	0
  3302                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3303                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3304                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3305                              <1> 	;
  3306                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3307                              <1>     	;		a page-protection violation. When not set,
  3308                              <1> 	;		it was caused by a non-present page.
  3309                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3310                              <1> 	;		a page write. When not set, it was caused
  3311                              <1> 	;		by a page read.
  3312                              <1> 	; U : USER    -	When set, the page fault was caused 
  3313                              <1> 	;		while CPL = 3. 
  3314                              <1> 	;		This does not necessarily mean that
  3315                              <1> 	;		the page fault was a privilege violation.
  3316                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3317                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3318                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3319                              <1> 	;     FETCH	an instruction fetch
  3320                              <1> 	;
  3321                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3322                              <1> 	;  31               22                  12 11                    0
  3323                              <1> 	; +-------------------+-------------------+-----------------------+
  3324                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3325                              <1>        	; +-------------------+-------------------+-----------------------+
  3326                              <1> 	;
  3327                              <1> 
  3328                              <1> 	;; CR3 REGISTER (Control Register 3)
  3329                              <1> 	;  31                                   12             5 4 3 2   0
  3330                              <1> 	; +---------------------------------------+-------------+---+-----+
  3331                              <1>       	; |                                       |  		|P|P|     |
  3332                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3333                              <1>       	; |                                       | 		|D|T|     |
  3334                              <1>    	; +---------------------------------------+-------------+---+-----+
  3335                              <1> 	;
  3336                              <1> 	;	PWT    - WRITE THROUGH
  3337                              <1> 	;	PCD    - CACHE DISABLE		
  3338                              <1> 	;
  3339                              <1> 	;
  3340                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3341                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3342                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3343                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3344                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3345                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3346                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3347                              <1> 	;
  3348                              <1>         ;       P      - PRESENT
  3349                              <1>         ;       R/W    - READ/WRITE
  3350                              <1>         ;       U/S    - USER/SUPERVISOR
  3351                              <1> 	;	PWT    - WRITE THROUGH
  3352                              <1> 	;	PCD    - CACHE DISABLE	
  3353                              <1> 	;	A      - ACCESSED	
  3354                              <1>         ;       D      - DIRTY (IGNORED)
  3355                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3356                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3357                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3358                              <1> 	;
  3359                              <1> 	;
  3360                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3361                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3362                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3363                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3364                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3365                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3366                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3367                              <1> 	;
  3368                              <1>         ;       P      - PRESENT
  3369                              <1>         ;       R/W    - READ/WRITE
  3370                              <1>         ;       U/S    - USER/SUPERVISOR
  3371                              <1> 	;	PWT    - WRITE THROUGH
  3372                              <1> 	;	PCD    - CACHE DISABLE	
  3373                              <1> 	;	A      - ACCESSED	
  3374                              <1>         ;       D      - DIRTY
  3375                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3376                              <1> 	;	G      - GLOBAL	 
  3377                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3378                              <1> 	;
  3379                              <1> 	;
  3380                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3381                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3382                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3383                              <1>       	; |                                       |     | | | | | | |U|R| |
  3384                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3385                              <1>       	; |                                       |     | | | | | | |S|W| |
  3386                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3387                              <1> 	;
  3388                              <1>         ;       P      - PRESENT
  3389                              <1>         ;       R/W    - READ/WRITE
  3390                              <1>         ;       U/S    - USER/SUPERVISOR
  3391                              <1>         ;       D      - DIRTY
  3392                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3393                              <1> 	;
  3394                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3395                              <1> 	;
  3396                              <1> 	;
  3397                              <1> 	;; Invalid Page Table Entry
  3398                              <1> 	; 31                                                           1 0
  3399                              <1>       	; +-------------------------------------------------------------+-+
  3400                              <1>       	; |                                                             | |
  3401                              <1>       	; |                          AVAILABLE                          |0|
  3402                              <1>       	; |                                                             | |
  3403                              <1>       	; +-------------------------------------------------------------+-+
  3404                              <1> 	;
  3405                              <1> 
  3406 000028B4 53                  <1> 	push	ebx
  3407 000028B5 52                  <1> 	push	edx
  3408 000028B6 51                  <1> 	push	ecx
  3409                              <1> 	;
  3410                              <1> 	; 21/09/2015 (debugging)
  3411 000028B7 FF05[01690000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3412 000028BD FF05[8C650000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3413                              <1> 	; 28/06/2015
  3414                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3415 000028C3 8A15[84650000]      <1> 	mov	dl, [error_code]
  3416                              <1> 	;
  3417 000028C9 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3418                              <1> 			; sign
  3419 000028CC 7425                <1> 	jz	short pfh_alloc_np
  3420                              <1> 	; 
  3421                              <1> 	; If it is not a 'write on read only page' type page fault
  3422                              <1> 	; major page fault error with minor reason must be returned without 
  3423                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3424                              <1> 	; after return here!
  3425                              <1> 	; Page fault will be remedied, by copying page contents
  3426                              <1> 	; to newly allocated page with write permission;
  3427                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3428                              <1> 	; used for working with minimum possible memory usage. 
  3429                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3430                              <1> 	; process with 'read only' flag. If the child process attempts to
  3431                              <1> 	; write on these read only pages, page fault will be directed here
  3432                              <1> 	; for allocating a new page with same data/content. 
  3433                              <1> 	;
  3434                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3435                              <1> 	; will not force to separate CODE and DATA space 
  3436                              <1> 	; in a process/program... 
  3437                              <1> 	; CODE segment/section may contain DATA!
  3438                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3439                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3440                              <1> 	;	
  3441 000028CE F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3442                              <1> 			; sign
  3443 000028D1 7418                <1>         jz      pfh_p_err
  3444                              <1> 	; 31/08/2015
  3445 000028D3 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3446                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3447 000028D6 7413                <1>         jz	short pfh_pv_err
  3448                              <1> 	;
  3449                              <1> 	; make a new page and copy the parent's page content
  3450                              <1> 	; as the child's new page content
  3451                              <1> 	;
  3452 000028D8 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3453                              <1> 			 ; which has caused to page fault
  3454 000028DB E87C000000          <1> 	call 	copy_page
  3455 000028E0 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3456                              <1> 	;
  3457 000028E2 EB72                <1>         jmp     pfh_cpp_ok
  3458                              <1> 
  3459                              <1> 	; 31/12/2021 (short jump)
  3460                              <1> pfh_im_err:
  3461 000028E4 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3462                              <1> 			; Major (Primary) Error: Page Fault
  3463                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3464 000028E9 EB6D                <1> 	jmp	short pfh_err_retn
  3465                              <1> 
  3466                              <1> 	; 31/12/2021
  3467                              <1> pfh_p_err: ; 09/03/2015
  3468                              <1> pfh_pv_err:
  3469                              <1> 	; Page fault was caused by a protection-violation
  3470 000028EB B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3471                              <1> 			; Major (Primary) Error: Page Fault
  3472                              <1> 			; Minor (Secondary) Error: Protection violation !
  3473 000028F0 F9                  <1> 	stc
  3474 000028F1 EB65                <1> 	jmp	short pfh_err_retn
  3475                              <1> 	
  3476                              <1> pfh_alloc_np:
  3477 000028F3 E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3478 000028F8 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3479                              <1> pfh_chk_cpl:
  3480                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3481                              <1> 		; (Lower 12 bits are ZERO, because 
  3482                              <1> 		;	the address is on a page boundary)
  3483 000028FA 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3484 000028FD 7505                <1> 	jnz	short pfh_um
  3485                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3486 000028FF 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3487                              <1> 			 ; of the current/active page directory
  3488                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3489                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3490 00002902 EB06                <1> 	jmp	short pfh_get_pde
  3491                              <1> 	;
  3492                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3493 00002904 8B1D[F1680000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3494                              <1> 			; Physical address of the USER's page directory
  3495                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3496                              <1> pfh_get_pde:
  3497 0000290A 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3498 0000290D 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3499                              <1> 			 ; which has been caused to page fault
  3500                              <1> 			 ;
  3501 00002910 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3502 00002913 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3503                              <1> 	;
  3504 00002916 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3505 00002918 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3506 0000291A F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3507 0000291D 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3508                              <1> 			  	  ; set/validate page directory entry
  3509 0000291F 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3510 00002924 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3511 00002926 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3512 00002928 EB16                <1> 	jmp	short pfh_get_pte
  3513                              <1> pfh_set_pde:
  3514                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3515                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3516                              <1> 	;
  3517 0000292A 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3518 0000292C 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3519 0000292E 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3520 00002930 89C3                <1> 	mov	ebx, eax
  3521 00002932 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3522 00002937 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3523                              <1> pfh_spde_1:
  3524                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3525 00002939 89C1                <1> 	mov	ecx, eax
  3526 0000293B E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3527                              <1> pfh_get_pte:
  3528 00002940 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3529                              <1> 			 ; which has been caused to page fault
  3530 00002943 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3531 00002945 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3532                              <1> 			 ; higher 20 bits of the page fault address 
  3533 00002948 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3534 0000294D C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3535 00002950 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3536                              <1> ; 24/12/2021
  3537                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3538                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3539                              <1> ; 24/12/2021
  3540                              <1> ; ('swap_in' procedure call has been disabled)
  3541                              <1> ;
  3542                              <1> ;	and	eax, eax
  3543                              <1> ;	jz	short pfh_gpte_1
  3544                              <1> ;	; 20/07/2015
  3545                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3546                              <1> ;	push	ebp ; 20/07/2015
  3547                              <1> ;	mov	ebp, cr2
  3548                              <1> ;		; ECX = physical address of the page table entry
  3549                              <1> ;		; EBX = Memory page address (physical!)
  3550                              <1> ;		; EAX = Swap disk (offset) address
  3551                              <1> ;		; EBP = virtual address (page fault address)
  3552                              <1> ;	call	swap_in
  3553                              <1> ;	pop	ebp
  3554                              <1> ;	jc      short pfh_err_retn
  3555                              <1> ;	xchg	ecx, ebx
  3556                              <1> ;		; EBX = physical address of the page table entry
  3557                              <1> ;		; ECX = new page
  3558                              <1> pfh_gpte_1:
  3559 00002952 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3560 00002954 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3561                              <1> pfh_cpp_ok:
  3562                              <1> ; 24/12/2021
  3563                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3564                              <1> ;
  3565                              <1> ;	; 20/07/2015
  3566                              <1> ;	mov	ebx, cr2
  3567                              <1> ;	call 	add_to_swap_queue
  3568                              <1> 	;
  3569                              <1> 	; The new PTE (which contains the new page) will be added to 
  3570                              <1> 	; the swap queue, here. 
  3571                              <1> 	; (Later, if memory will become insufficient, 
  3572                              <1> 	; one page will be swapped out which is at the head of 
  3573                              <1> 	; the swap queue by using FIFO and access check methods.)
  3574                              <1> 	;
  3575 00002956 31C0                <1> 	xor	eax, eax  ; 0
  3576                              <1> 	;
  3577                              <1> pfh_err_retn:
  3578 00002958 59                  <1> 	pop	ecx
  3579 00002959 5A                  <1> 	pop	edx
  3580 0000295A 5B                  <1> 	pop	ebx
  3581 0000295B C3                  <1> 	retn 
  3582                              <1> 	
  3583                              <1> copy_page:
  3584                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3585                              <1> 	; 16/04/2021
  3586                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3587                              <1> 	; 22/09/2015
  3588                              <1> 	; 21/09/2015
  3589                              <1> 	; 19/09/2015
  3590                              <1> 	; 07/09/2015
  3591                              <1> 	; 31/08/2015
  3592                              <1> 	; 20/07/2015
  3593                              <1> 	; 05/05/2015
  3594                              <1> 	; 03/05/2015
  3595                              <1> 	; 18/04/2015
  3596                              <1> 	; 12/04/2015
  3597                              <1> 	; 30/10/2014
  3598                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3599                              <1> 	;
  3600                              <1> 	; INPUT -> 
  3601                              <1> 	;	EBX = Virtual (linear) address of source page
  3602                              <1> 	;	     (Page fault address)
  3603                              <1> 	; OUTPUT ->
  3604                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3605                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3606                              <1> 	;	EAX = 0 (CF = 1) 
  3607                              <1> 	;		if there is not a free page to be allocated
  3608                              <1> 	;	(page content of the source page will be copied
  3609                              <1> 	;	onto the target/new page) 	
  3610                              <1> 	;
  3611                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3612                              <1> 	;
  3613                              <1> 
  3614                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3615                              <1> 	; INPUT: 
  3616                              <1> 	;	EBX = Virtual (linear) address of source page
  3617                              <1> 	;	     (Page fault address)
  3618                              <1> 	; OUTPUT:
  3619                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3620                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3621                              <1> 	;	EAX = 0 (CF = 1) 
  3622                              <1> 	;		if there is not a free page to be allocated
  3623                              <1> 	;	(page content of the source page will be copied
  3624                              <1> 	;	onto the target/new page) 	
  3625                              <1> 	;
  3626                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3627                              <1> 	
  3628 0000295C 56                  <1> 	push	esi ; *
  3629 0000295D 57                  <1> 	push	edi ; **
  3630                              <1> 	; 16/04/2021
  3631                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3632                              <1> 	;push	ebx ; ***
  3633                              <1> 	;push	ecx ; ****
  3634 0000295E 31F6                <1> 	xor 	esi, esi
  3635 00002960 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3636 00002963 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3637 00002965 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3638 00002968 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3639 0000296B 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3640 0000296D 031D[F1680000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3641 00002973 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3642 00002975 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3643 00002979 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3644 0000297B 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3645 00002981 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3646 00002985 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3647                              <1> 	; 07/09/2015
  3648 00002987 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3649                              <1> 				     ; read only page as a child process?)	
  3650 0000298C 7509                <1> 	jnz	short cpp_0 ; yes
  3651 0000298E 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3652 00002990 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3653 00002995 EB32                <1> 	jmp	short cpp_1
  3654                              <1> cpp_0:
  3655 00002997 89FE                <1> 	mov	esi, edi
  3656 00002999 0335[F5680000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3657 0000299F 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3658 000029A1 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3659 000029A5 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3660 000029A7 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3661 000029AD 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3662 000029B1 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3663 000029B3 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3664                              <1> 	; 21/09/2015
  3665 000029B5 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3666 000029B7 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3667                              <1> 	;
  3668 000029BB F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3669 000029BE 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3670                              <1> 	;
  3671 000029C0 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3672 000029C5 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3673 000029C7 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3674                              <1> 			    ; Convert child's page to writable page
  3675                              <1> cpp_1:
  3676 000029C9 E833FCFFFF          <1> 	call	allocate_page
  3677 000029CE 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3678 000029D0 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3679 000029D2 7405                <1> 	jz	short cpp_2
  3680                              <1> 		; Convert read only page to writable page 
  3681                              <1> 		;(for the parent of the current process)
  3682                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3683                              <1> 	; 22/09/2015
  3684 000029D4 890E                <1> 	mov	[esi], ecx
  3685 000029D6 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3686                              <1> 				 ; 1+2+4 = 7
  3687                              <1> cpp_2:
  3688 000029D9 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3689                              <1> 	; 07/09/2015
  3690 000029DB 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3691 000029DD B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3692 000029E2 F3A5                <1> 	rep	movsd ; 31/08/2015
  3693                              <1> cpp_3:		
  3694 000029E4 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3695 000029E6 8903                <1> 	mov	[ebx], eax ; Update PTE
  3696 000029E8 28C0                <1> 	sub	al, al ; clear attributes
  3697                              <1> cpp_4:
  3698                              <1> 	; 16/04/2021
  3699                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3700                              <1> 	;pop	ecx ; ****
  3701                              <1> 	;pop	ebx ; ***
  3702 000029EA 5F                  <1> 	pop	edi ; **
  3703 000029EB 5E                  <1> 	pop	esi ; *
  3704 000029EC C3                  <1> 	retn
  3705                              <1> 
  3706                              <1> ;; 28/04/2015
  3707                              <1> ;; 24/10/2014
  3708                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3709                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3710                              <1> ;;
  3711                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3712                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3713                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3714                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3715                              <1> ;;
  3716                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3717                              <1> ;;
  3718                              <1> ;; Method:
  3719                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3720                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3721                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3722                              <1> ;;	When a new page is being allocated, swap queue is updated
  3723                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3724                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3725                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3726                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3727                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3728                              <1> ;;	offset value becomes it's previous offset value - 4.
  3729                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3730                              <1> ;;	the queue/list is not shifted.
  3731                              <1> ;;	After the queue/list shift, newly allocated page is added
  3732                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3733                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3734                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3735                              <1> ;;	
  3736                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3737                              <1> ;;	the first non-accessed, writable page in the list, 
  3738                              <1> ;;	from the head to the tail. The list is shifted to left 
  3739                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3740                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3741                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3742                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3743                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3744                              <1> ;;	procedure will be failed)...
  3745                              <1> ;;
  3746                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3747                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3748                              <1> ;;	(PTE) will be added to the tail of the queue after
  3749                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3750                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3751                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3752                              <1> ;;
  3753                              <1> ;;
  3754                              <1> ;;	
  3755                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3756                              <1> ;;
  3757                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3758                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3759                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3760                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3761                              <1> ;;
  3762                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3763                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3764                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3765                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3766                              <1> ;; 		 (entire swap space must be accessed by using
  3767                              <1> ;;		 31 bit offset address) 
  3768                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3769                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3770                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3771                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3772                              <1> ;;
  3773                              <1> ;; 					
  3774                              <1> ;; Method:
  3775                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3776                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3777                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3778                              <1> ;;	Swapping out is performed by using swap page queue.
  3779                              <1> ;;
  3780                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3781                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3782                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3783                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3784                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3785                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3786                              <1> ;;	calculated by adding offset value to the swap partition's 
  3787                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3788                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3789                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3790                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3791                              <1> ;;	is in a partitioned virtual hard disk.) 
  3792                              <1> ;;
  3793                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3794                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3795                              <1> ;;
  3796                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3797                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3798                              <1> ;;
  3799                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3800                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3801                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3802                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3803                              <1> ;;	it means relevant (respective) block is in use, and, 
  3804                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3805                              <1> ;;      swap disk/file block is free.
  3806                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3807                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3808                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3809                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3810                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3811                              <1> ;;	------------------------------------------------------------
  3812                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3813                              <1> ;;	------------------------------------------------------------
  3814                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3815                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3816                              <1> ;;
  3817                              <1> ;;	..............................................................
  3818                              <1> ;;
  3819                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3820                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3821                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3822                              <1> ;;	position with value of 1 on the table is converted to swap
  3823                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3824                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3825                              <1> ;;	number of physical swap disk or virtual swap disk)
  3826                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3827                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3828                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3829                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3830                              <1> ;;	If disk write procedure returns with error or free count of 
  3831                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3832                              <1> ;;	'insufficient memory error' (cf=1). 
  3833                              <1> ;;
  3834                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3835                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3836                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3837                              <1> ;;	free blocks after a disk write error. It will return to 
  3838                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3839                              <1> ;;
  3840                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3841                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3842                              <1> ;;	address (cf=0). 
  3843                              <1> ;;
  3844                              <1> ;;	..............................................................
  3845                              <1> ;;
  3846                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3847                              <1> ;;	file sectors at specified memory page. Then page allocation
  3848                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3849                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3850                              <1> ;;	to do, except to terminate the process which is the owner of
  3851                              <1> ;;	the swapped page.
  3852                              <1> ;;
  3853                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3854                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3855                              <1> ;;	updates [swpd_first] pointer if it is required.
  3856                              <1> ;;
  3857                              <1> ;;	..............................................................	 
  3858                              <1> ;;
  3859                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3860                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3861                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3862                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3863                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3864                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3865                              <1> ;;
  3866                              <1> 
  3867                              <1> ; 24/12/2021
  3868                              <1> ; ('swap_in' procedure call is disabled)
  3869                              <1> 
  3870                              <1> ;swap_in:
  3871                              <1> 	; 31/08/2015
  3872                              <1> 	; 20/07/2015
  3873                              <1> 	; 28/04/2015
  3874                              <1> 	; 18/04/2015
  3875                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3876                              <1> 	;
  3877                              <1> 	; INPUT -> 
  3878                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3879                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3880                              <1> 	;	EAX = Offset Address for the swapped page on the
  3881                              <1> 	;	      swap disk or in the swap file.
  3882                              <1> 	;
  3883                              <1> 	; OUTPUT ->
  3884                              <1> 	;	EAX = 0 if loading at memory has been successful
  3885                              <1> 	;
  3886                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3887                              <1> 	;		  or sector not present or drive not ready
  3888                              <1> 	;	     EAX = Error code
  3889                              <1> 	;	     [u.error] = EAX 
  3890                              <1> 	;		       = The last error code for the process
  3891                              <1> 	;		         (will be reset after returning to user)	  
  3892                              <1> 	;
  3893                              <1> 	; Modified Registers -> EAX
  3894                              <1> 	;
  3895                              <1> 
  3896                              <1> ;       cmp     dword [swp_drv], 0
  3897                              <1> ;	jna	short swpin_dnp_err
  3898                              <1> ;
  3899                              <1> ;	cmp	eax, [swpd_size]
  3900                              <1> ;	jnb	short swpin_snp_err
  3901                              <1> ;
  3902                              <1> ;	push	esi
  3903                              <1> ;	push	ebx
  3904                              <1> ;	push	ecx
  3905                              <1> ;	mov	esi, [swp_drv]	
  3906                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3907                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3908                              <1> ;		; size different than 512 bytes, logical disk sector
  3909                              <1> ;		; size is 512 bytes and disk reading procedure
  3910                              <1> ;		; will be performed for reading 4096 bytes
  3911                              <1> ;		; (2*2048, 8*512). 
  3912                              <1> ;	; ESI = Logical disk description table address
  3913                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3914                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3915                              <1> ;	; ECX = Sector count ; 8 sectors
  3916                              <1> ;	push	eax
  3917                              <1> ;	call	logical_disk_read
  3918                              <1> ;	pop	eax
  3919                              <1> ;	jnc	short swpin_read_ok
  3920                              <1> ;	;
  3921                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3922                              <1> ;	mov	[u.error], eax
  3923                              <1> ;	jmp	short swpin_retn
  3924                              <1> ;	;
  3925                              <1> ;swpin_read_ok:
  3926                              <1> ;	; EAX = Offset address (logical sector number)
  3927                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3928                              <1> ;	;
  3929                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3930                              <1> ;	; 20/07/2015
  3931                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3932                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3933                              <1> ;	mov	bl, [u.uno] ; current process number
  3934                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3935                              <1> ;	call	swap_queue_shift
  3936                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3937                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3938                              <1> ;	; zf = 1
  3939                              <1> ;swpin_retn:
  3940                              <1> ;	pop	ecx
  3941                              <1> ;	pop	ebx
  3942                              <1> ;	pop	esi
  3943                              <1> ;	retn
  3944                              <1> ;
  3945                              <1> ;swpin_dnp_err:
  3946                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3947                              <1> ;swpin_err_retn:
  3948                              <1> ;	mov	[u.error], eax
  3949                              <1> ;	stc
  3950                              <1> ;	retn
  3951                              <1> ;
  3952                              <1> ;swpin_snp_err:
  3953                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3954                              <1> ;	jmp	short swpin_err_retn
  3955                              <1> 
  3956                              <1> ; 24/12/2021
  3957                              <1> ; ('swap_out' procedure call is disabled)
  3958                              <1> 
  3959                              <1> ;swap_out:
  3960                              <1> 	; 10/06/2016
  3961                              <1> 	; 07/06/2016
  3962                              <1>         ; 23/05/2016
  3963                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3964                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3965                              <1> 	;
  3966                              <1> 	; INPUT -> 
  3967                              <1> 	;	none
  3968                              <1> 	;
  3969                              <1> 	; OUTPUT ->
  3970                              <1> 	;	EAX = Physical page address (which is swapped out
  3971                              <1> 	;	      for allocating a new page)
  3972                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3973                              <1> 	;		  or sector not present or drive not ready
  3974                              <1> 	;	     EAX = Error code
  3975                              <1> 	;	     [u.error] = EAX 
  3976                              <1> 	;		       = The last error code for the process
  3977                              <1> 	;		         (will be reset after returning to user)	  
  3978                              <1> 	;
  3979                              <1> 	; Modified Registers -> none (except EAX)
  3980                              <1> 	;
  3981                              <1> 
  3982                              <1> ;	cmp 	word [swpq_count], 1
  3983                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3984                              <1> ;
  3985                              <1> ;       ;cmp    dword [swp_drv], 1
  3986                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3987                              <1> ;
  3988                              <1> ;       cmp     dword [swpd_free], 1
  3989                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3990                              <1> ;
  3991                              <1> ;	push	ebx ; *
  3992                              <1> ;swpout_1:
  3993                              <1> ;	; 10/06/2016
  3994                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3995                              <1> ;	call	swap_queue_shift
  3996                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3997                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3998                              <1> ;				       ; pointer in the swap queue
  3999                              <1> ;	; EAX = PTE value of the page
  4000                              <1> ;	; EBX = PTE address of the page
  4001                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4002                              <1> ;	;
  4003                              <1> ;	; 07/06/2016
  4004                              <1> ;	; 19/05/2016
  4005                              <1> ;	; check this page is in timer events or not
  4006                              <1> ;	
  4007                              <1> ;swpout_timer_page_0:
  4008                              <1> ;	push	edx ; **
  4009                              <1> ;
  4010                              <1> ;	; 07/06/2016
  4011                              <1> ;	cmp	byte [timer_events], 0 
  4012                              <1> ;	jna	short swpout_2
  4013                              <1> ;	;
  4014                              <1> ;	mov	dl, [timer_events]
  4015                              <1> ;
  4016                              <1> ;	push	ecx ; ***
  4017                              <1> ;	push	ebx ; ****
  4018                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4019                              <1> ;			       ; structures 
  4020                              <1> ;swpout_timer_page_1:
  4021                              <1> ;	mov	cl, [ebx]
  4022                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4023                              <1> ;	jz	short swpout_timer_page_3
  4024                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4025                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4026                              <1> ;				; of the response byte address, to
  4027                              <1> ;				; get beginning of the page address)
  4028                              <1> ;	cmp	eax, ecx
  4029                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4030                              <1> ;	
  4031                              <1> ;	; !same page!
  4032                              <1> ;	;
  4033                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4034                              <1> ;	; This page will be used by the kernel to put timer event
  4035                              <1> ;	; response (signal return) byte at the requested address;
  4036                              <1> ;	; in order to prevent a possible wrong write (while
  4037                              <1> ;	; this page is swapped out) on physical memory,
  4038                              <1> ;	; we must protect this page against to be swapped out!
  4039                              <1> ;	;
  4040                              <1> ;	pop	ebx ; ****
  4041                              <1> ;	pop	ecx ; ***
  4042                              <1> ;	pop	edx ; **
  4043                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4044                              <1> ; 
  4045                              <1> ;swpout_timer_page_2:
  4046                              <1> ;	; 07/06/2016
  4047                              <1> ;	dec	dl
  4048                              <1> ;	jz	short swpout_timer_page_4
  4049                              <1> ;swpout_timer_page_3:
  4050                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4051                              <1> ;	;jnb	short swpout_timer_page_4
  4052                              <1> ;	add	ebx, 16
  4053                              <1> ;	jmp	short swpout_timer_page_1	
  4054                              <1> ;
  4055                              <1> ;swpout_timer_page_4:
  4056                              <1> ;	pop	ebx ; ****
  4057                              <1> ;	pop	ecx ; ***
  4058                              <1> ;swpout_2:
  4059                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4060                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4061                              <1> ;	;
  4062                              <1> ;	call	link_swap_block
  4063                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4064                              <1> ;				       ; because [swpd_free] value
  4065                              <1> ;				       ; was checked at the beginging. 	
  4066                              <1> ;	pop	edx ; **
  4067                              <1> ;	pop	ebx ; *
  4068                              <1> ;	jmp	short swpout_nfspc_err 
  4069                              <1> ;swpout_3:
  4070                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4071                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4072                              <1> ;	;	
  4073                              <1> ;	push	esi ; **
  4074                              <1> ;	push	ecx ; ***
  4075                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4076                              <1> ;	mov	esi, [swp_drv]	
  4077                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4078                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4079                              <1> ;		; size different than 512 bytes, logical disk sector
  4080                              <1> ;		; size is 512 bytes and disk writing procedure
  4081                              <1> ;		; will be performed for writing 4096 bytes
  4082                              <1> ;		; (2*2048, 8*512). 
  4083                              <1> ;	; ESI = Logical disk description table address
  4084                              <1> ;	; EBX = Buffer (Page) address
  4085                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4086                              <1> ;	; ECX = Sector count ; 8 sectors
  4087                              <1> ;	; edx = PTE address
  4088                              <1> ;	call	logical_disk_write
  4089                              <1> ;	; edx = PTE address
  4090                              <1> ;	pop	ecx ; sector address	
  4091                              <1> ;	jnc	short swpout_write_ok
  4092                              <1> ;	;
  4093                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4094                              <1> ;swpout_dw_err:
  4095                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4096                              <1> ;	mov	[u.error], eax
  4097                              <1> ;	jmp	short swpout_retn
  4098                              <1> ;	;
  4099                              <1> ;swpout_write_ok:
  4100                              <1> ;	; EBX = Buffer (page) address
  4101                              <1> ;	; EDX = Page Table Entry address
  4102                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4103                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4104                              <1> ;	mov 	[edx], ecx 
  4105                              <1> ;		; bit 0 = 0 (swapped page)
  4106                              <1> ;	mov	eax, ebx
  4107                              <1> ;swpout_retn:
  4108                              <1> ;	pop	ecx ; ***
  4109                              <1> ;	pop	esi ; **
  4110                              <1> ;	pop	ebx ; *
  4111                              <1> ;	retn
  4112                              <1> ;
  4113                              <1> ;;swpout_dnp_err:
  4114                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4115                              <1> ;;	jmp	short swpout_err_retn
  4116                              <1> ;swpout_nfspc_err:
  4117                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4118                              <1> ;swpout_err_retn:
  4119                              <1> ;	mov	[u.error], eax
  4120                              <1> ;	;stc
  4121                              <1> ;	retn
  4122                              <1> ;swpout_npts_err:
  4123                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4124                              <1> ;	pop	ebx
  4125                              <1> ;	jmp	short swpout_err_retn
  4126                              <1> ;swpout_im_err:
  4127                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4128                              <1> ;	jmp	short swpout_err_retn
  4129                              <1> 
  4130                              <1> ; 24/12/2021
  4131                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4132                              <1> 
  4133                              <1> ;swap_queue_shift:
  4134                              <1> 	; 26/03/2017
  4135                              <1> 	; 10/06/2016
  4136                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4137                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4138                              <1> 	;
  4139                              <1> 	; INPUT ->
  4140                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4141                              <1> 	;	      and process number combination (bit 0 to 11)
  4142                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4143                              <1> 	;	
  4144                              <1> 	; OUTPUT ->
  4145                              <1> 	;	If EBX input > 0 
  4146                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4147                              <1> 	; 	   from the tail to the head, up to entry offset
  4148                              <1> 	; 	   which points to EBX input value or nothing
  4149                              <1> 	;	   to do if EBX value is not found on the queue.
  4150                              <1> 	;	   (The entry -with EBX value- will be removed
  4151                              <1> 	;	   from the queue if it is found.)
  4152                              <1> 	;
  4153                              <1> 	;	   EAX = 0		
  4154                              <1> 	;
  4155                              <1> 	;	If EBX input = 0
  4156                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4157                              <1> 	; 	   from the tail to the head, if the PTE address
  4158                              <1> 	;	   which is pointed in head of the queue is marked
  4159                              <1> 	;	   as "accessed" or it is marked as "non present".
  4160                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4161                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4162                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4163                              <1> 	;	   -without dropping pointer of the PTE from 
  4164                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4165                              <1> 	;	   Pointer in the head will be moved into the tail,
  4166                              <1> 	;	   other PTEs will be shifted on head direction.)
  4167                              <1> 	;
  4168                              <1> 	;	   Swap queue will be shifted up to the first
  4169                              <1> 	;	   'present' or 'non accessed' page will be found
  4170                              <1> 	;	   (as pointed) on the queue head (then it will be
  4171                              <1>         ;          removed/dropped from the queue).
  4172                              <1> 	;
  4173                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4174                              <1> 	;		 (it's pointer -virtual address-) dropped
  4175                              <1> 	;		 (removed) from swap queue.
  4176                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4177                              <1> 	;	         which is (it's pointer -virtual address-)
  4178                              <1> 	;		 dropped (removed) from swap queue.
  4179                              <1> 	;
  4180                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4181                              <1> 	;
  4182                              <1> 	; Modified Registers -> EAX, EBX
  4183                              <1> 	;
  4184                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4185                              <1> ;	and	ax, ax
  4186                              <1> ;	jz	short swpqs_retn
  4187                              <1> ;	push	edi
  4188                              <1> ;	push	esi
  4189                              <1> ;	push	ecx
  4190                              <1> ;	mov	esi, swap_queue
  4191                              <1> ;	mov	ecx, eax
  4192                              <1> ;	or	ebx, ebx
  4193                              <1> ;	jz	short swpqs_7
  4194                              <1> ;swpqs_1:
  4195                              <1> ;	lodsd
  4196                              <1> ;	cmp	eax, ebx
  4197                              <1> ;	je	short swpqs_2
  4198                              <1> ;	loop	swpqs_1
  4199                              <1> ;	; 10/06/2016
  4200                              <1> ;	sub	eax, eax 
  4201                              <1> ;	jmp	short swpqs_6
  4202                              <1> ;swpqs_2:
  4203                              <1> ;	mov	edi, esi
  4204                              <1> ;	sub 	edi, 4
  4205                              <1> ;swpqs_3:
  4206                              <1> ;	dec	word [swpq_count]
  4207                              <1> ;	jz	short swpqs_5
  4208                              <1> ;swpqs_4:
  4209                              <1> ;	dec 	ecx
  4210                              <1> ;	rep	movsd	; shift up (to the head)
  4211                              <1> ;swpqs_5:
  4212                              <1> ;	xor	eax, eax
  4213                              <1> ;	mov	[edi], eax
  4214                              <1> ;swpqs_6:
  4215                              <1> ;	pop	ecx
  4216                              <1> ;	pop	esi
  4217                              <1> ;	pop	edi
  4218                              <1> ;swpqs_retn:
  4219                              <1> ;	retn		
  4220                              <1> ;swpqs_7:
  4221                              <1> ;	mov	edi, esi ; head
  4222                              <1> ;	lodsd
  4223                              <1> ;	; 20/07/2015
  4224                              <1> ;	mov	ebx, eax
  4225                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4226                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4227                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4228                              <1> ;		      ; ax = process number (1 to 4095)
  4229                              <1> ;	cmp	al, [u.uno]
  4230                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4231                              <1> ;	jne	short swpqs_8
  4232                              <1> ;	mov	eax, [u.pgdir]
  4233                              <1> ;	jmp	short swpqs_9
  4234                              <1> ;swpqs_8:
  4235                              <1> ;	; 09/06/2016
  4236                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4237                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4238                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4239                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4240                              <1> ;
  4241                              <1> ;	;shl	ax, 2
  4242                              <1> ;	shl	al, 2
  4243                              <1> ;	mov 	eax, [eax+p.upage-4]
  4244                              <1> ;	or	eax, eax
  4245                              <1> ;	jz	short swpqs_3 ; invalid upage
  4246                              <1> ;	add	eax, u.pgdir - user
  4247                              <1> ;			 ; u.pgdir value for the process
  4248                              <1> ;			 ; is in [eax]
  4249                              <1> ;	mov	eax, [eax]
  4250                              <1> ;	and	eax, eax
  4251                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4252                              <1> ;swpqs_9:
  4253                              <1> ;	push	edx
  4254                              <1> ;	; eax = page directory
  4255                              <1> ;	; ebx = virtual address
  4256                              <1> ;	call	get_pte
  4257                              <1> ;	mov	ebx, edx	; PTE address
  4258                              <1> ;	pop	edx
  4259                              <1> ;	; 10/06/2016
  4260                              <1> ;	jc	short swpqs_13 ; empty PDE
  4261                              <1> ;	; EAX = PTE value
  4262                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4263                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4264                              <1> ;			        ; from the queue (head)
  4265                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4266                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4267                              <1> ;			        ; from the queue (head) 	
  4268                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4269                              <1> ;	;jnz	short swpqs_11  ; present
  4270                              <1> ;			        ; accessed page
  4271                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4272                              <1> ;	jc	short swpqs_11  ; accessed page
  4273                              <1> ;
  4274                              <1> ;	dec	ecx
  4275                              <1> ;	mov	[swpq_count], cx
  4276                              <1> ;       jz      short swpqs_10
  4277                              <1> ;		; esi = head + 4
  4278                              <1> ;		; edi = head
  4279                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4280                              <1> ;swpqs_10:
  4281                              <1> ;	mov	[edi], ecx ; 0
  4282                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4283                              <1> ;
  4284                              <1> ;swpqs_11:
  4285                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4286                              <1> ;	; Rotation (head -> tail)
  4287                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4288                              <1> ;	jz	short swpqs_10
  4289                              <1> ;		; esi = head + 4
  4290                              <1> ;		; edi = head
  4291                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4292                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4293                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4294                              <1> ;
  4295                              <1> ;	mov	cx, [swpq_count]
  4296                              <1> ;
  4297                              <1> ;swpqs_12:
  4298                              <1> ;	mov	esi, swap_queue ; head
  4299                              <1> ;       jmp     swpqs_7
  4300                              <1> ;
  4301                              <1> ;swpqs_13:
  4302                              <1> ;	dec	ecx
  4303                              <1> ;	mov	[swpq_count], cx
  4304                              <1> ;       jz      swpqs_5
  4305                              <1> ;	jmp	short swpqs_12
  4306                              <1> 
  4307                              <1> ; 24/12/2021
  4308                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4309                              <1> 
  4310                              <1> ;add_to_swap_queue:
  4311                              <1> 	; 20/02/2017
  4312                              <1> 	; 20/07/2015
  4313                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4314                              <1> 	;
  4315                              <1> 	; Adds new page to swap queue
  4316                              <1> 	; (page directories and page tables must not be added
  4317                              <1> 	; to swap queue)	
  4318                              <1> 	;
  4319                              <1> 	; INPUT ->
  4320                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4321                              <1> 	;	[u.uno]
  4322                              <1> 	;	20/02/2017
  4323                              <1> 	;	(Linear address = CORE + user's virtual address)
  4324                              <1> 	;
  4325                              <1> 	; OUTPUT ->
  4326                              <1> 	;	EAX = [swpq_count]
  4327                              <1> 	;	      (after the PTE has been added)
  4328                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4329                              <1> 	;	      the PTE could not be added.
  4330                              <1> 	;
  4331                              <1> 	; Modified Registers -> EAX
  4332                              <1> 	;
  4333                              <1> ;	push	ebx
  4334                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4335                              <1> ;	mov	bl, [u.uno] ; current process number
  4336                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4337                              <1> ;				 ; it is already on the queue
  4338                              <1> ;		; then add it to the tail of the queue
  4339                              <1> ;	movzx	eax, word [swpq_count]
  4340                              <1> ;	cmp	ax, 1024
  4341                              <1> ;	jb	short atsq_1
  4342                              <1> ;	sub	ax, ax
  4343                              <1> ;	pop	ebx
  4344                              <1> ;	retn
  4345                              <1> ;atsq_1:
  4346                              <1> ;	push	esi
  4347                              <1> ;	mov	esi, swap_queue
  4348                              <1> ;	and	ax, ax
  4349                              <1> ;	jz	short atsq_2
  4350                              <1> ;	shl	ax, 2	; convert to offset
  4351                              <1> ;	add	esi, eax
  4352                              <1> ;	shr	ax, 2
  4353                              <1> ;atsq_2:
  4354                              <1> ;	inc	ax
  4355                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4356                              <1> ;	mov	[swpq_count], ax
  4357                              <1> ;	pop	esi
  4358                              <1> ;	pop	ebx
  4359                              <1> ;	retn
  4360                              <1> 
  4361                              <1> ; 24/12/2021
  4362                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4363                              <1> 
  4364                              <1> ;unlink_swap_block:
  4365                              <1> 	; 15/09/2015
  4366                              <1> 	; 30/04/2015
  4367                              <1> 	; 18/04/2015
  4368                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4369                              <1> 	;
  4370                              <1> 	; INPUT -> 
  4371                              <1> 	;	EAX = swap disk/file offset address
  4372                              <1> 	;	      (bit 1 to bit 31)
  4373                              <1> 	; OUTPUT ->
  4374                              <1> 	;	[swpd_free] is increased
  4375                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4376                              <1> 	;
  4377                              <1> 	; Modified Registers -> EAX
  4378                              <1> 	;
  4379                              <1> ;	push	ebx
  4380                              <1> ;	push	edx
  4381                              <1> ;	;
  4382                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4383                              <1> ;				     ; 3 bits right
  4384                              <1> ;				     ; to get swap block/page number
  4385                              <1> ;	mov	edx, eax
  4386                              <1> ;	; 15/09/2015
  4387                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4388                              <1> ;				     ; (1 allocation bit = 1 page)
  4389                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4390                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4391                              <1> ;				     ; (to get 32 bit position)			
  4392                              <1> ;	;
  4393                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4394                              <1> ;	add	ebx, edx
  4395                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4396                              <1> ;				     ; (allocation bit position)	 
  4397                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4398                              <1> ;				     ; than the address in 'swpd_next' ?
  4399                              <1> ;				     ; (next/first free block value)		
  4400                              <1> ;	jnb	short uswpbl_1	     ; no	
  4401                              <1> ;	mov	[swpd_next], eax     ; yes	
  4402                              <1> ;uswpbl_1:
  4403                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4404                              <1> ;				     ; set relevant bit to 1.
  4405                              <1> ;				     ; set CF to the previous bit value	
  4406                              <1> ;	cmc			     ; complement carry flag	
  4407                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4408                              <1> ;				     ; if the block is already deallocated
  4409                              <1> ;				     ; before.	
  4410                              <1> ;       inc     dword [swpd_free]
  4411                              <1> ;uswpbl_2:
  4412                              <1> ;	pop	edx
  4413                              <1> ;	pop	ebx
  4414                              <1> ;	retn
  4415                              <1> 
  4416                              <1> ; 24/12/2021
  4417                              <1> ; ('link_swap_block' procedure call is disabled)
  4418                              <1> 
  4419                              <1> ;link_swap_block:
  4420                              <1> 	; 01/07/2015
  4421                              <1> 	; 18/04/2015
  4422                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4423                              <1> 	;
  4424                              <1> 	; INPUT -> none
  4425                              <1> 	;
  4426                              <1> 	; OUTPUT ->
  4427                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4428                              <1> 	;	      in sectors (corresponding 
  4429                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4430                              <1> 	;
  4431                              <1> 	;	CF = 1 and EAX = 0 
  4432                              <1> 	; 		   if there is not a free block to be allocated	
  4433                              <1> 	;
  4434                              <1> 	; Modified Registers -> none (except EAX)
  4435                              <1> 	;
  4436                              <1> 
  4437                              <1> ;	;mov	eax, [swpd_free]
  4438                              <1> ;	;and	eax, eax
  4439                              <1> ;	;jz	short out_of_swpspc
  4440                              <1> ;	;
  4441                              <1> ;	push	ebx
  4442                              <1> ;	push	ecx
  4443                              <1> ;	;
  4444                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4445                              <1> ;	mov	ecx, ebx
  4446                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4447                              <1> ;				 ; next_free_swap_block >> 5
  4448                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4449                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4450                              <1> ;lswbl_scan:
  4451                              <1> ;	cmp	ebx, ecx
  4452                              <1> ;	ja	short lswbl_notfound
  4453                              <1> ;	;
  4454                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4455                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4456                              <1> ;			   ; loads the destination with an index to
  4457                              <1> ;			   ; first set bit. (0 -> 31) 
  4458                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4459                              <1> ;	; 01/07/2015
  4460                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4461                              <1> ;			 ;
  4462                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4463                              <1> ;			 ;	  with value of 1 means 
  4464                              <1> ;			 ;	  the corresponding page is free 
  4465                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4466                              <1> ;	add	ebx, 4
  4467                              <1> ;			 ; We return back for searching next page block
  4468                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4469                              <1> ;			 ;	 we always will find at least 1 free block here.
  4470                              <1> ;	jmp    	short lswbl_scan
  4471                              <1> ;	;
  4472                              <1> ;lswbl_notfound:	
  4473                              <1> ;	sub	ecx, swap_alloc_table
  4474                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4475                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4476                              <1> ;	xor	eax, eax
  4477                              <1> ;	mov	[swpd_free], eax
  4478                              <1> ;	stc
  4479                              <1> ;lswbl_ok:
  4480                              <1> ;	pop	ecx
  4481                              <1> ;	pop	ebx
  4482                              <1> ;	retn
  4483                              <1> ;	;
  4484                              <1> ;;out_of_swpspc:
  4485                              <1> ;;	stc
  4486                              <1> ;;	retn
  4487                              <1> ;
  4488                              <1> ;lswbl_found:
  4489                              <1> ;	mov	ecx, ebx
  4490                              <1> ;	sub	ecx, swap_alloc_table
  4491                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4492                              <1> ;				 ; address/offset (to the next)
  4493                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4494                              <1> ;	;
  4495                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4496                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4497                              <1> ;				 ; in the destination.
  4498                              <1> ;				 ;
  4499                              <1> ;				 ; Reset the bit which is corresponding to the 
  4500                              <1> ;				 ; (just) allocated block.
  4501                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4502                              <1> ;	add	eax, ecx	 ; = block number
  4503                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4504                              <1> ;				 ; 1 block =  8 sectors
  4505                              <1> ;	;
  4506                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4507                              <1> ;	;
  4508                              <1> ;	; NOTE: The relevant page table entry will be updated
  4509                              <1> ;	;       according to this EAX value...
  4510                              <1> ;	;
  4511                              <1> ;	jmp	short lswbl_ok
  4512                              <1> 
  4513                              <1> ; 24/12/2021
  4514                              <1> ; ('logical_disk_read' procedure call is disabled)
  4515                              <1> 
  4516                              <1> ;logical_disk_read:
  4517                              <1> 	; 20/07/2015
  4518                              <1> 	; 09/03/2015 (temporary code here)
  4519                              <1> 	;
  4520                              <1> 	; INPUT ->
  4521                              <1> 	; 	ESI = Logical disk description table address
  4522                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4523                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4524                              <1> 	; 	ECX = Sector count
  4525                              <1> 	;
  4526                              <1> 	;
  4527                              <1> ;	retn
  4528                              <1> 
  4529                              <1> ; 24/12/2021
  4530                              <1> ; ('logical_disk_write' procedure call is disabled)
  4531                              <1> 
  4532                              <1> ;logical_disk_write:
  4533                              <1> 	; 20/07/2015
  4534                              <1> 	; 09/03/2015 (temporary code here)
  4535                              <1> 	;
  4536                              <1> 	; INPUT ->
  4537                              <1> 	; 	ESI = Logical disk description table address
  4538                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4539                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4540                              <1> 	; 	ECX = Sector count
  4541                              <1> 	;
  4542                              <1> ;	retn
  4543                              <1> 
  4544                              <1> get_physical_addr:
  4545                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4546                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4547                              <1> 	; 18/10/2015
  4548                              <1> 	; 29/07/2015
  4549                              <1> 	; 20/07/2015
  4550                              <1> 	; 04/06/2015
  4551                              <1> 	; 20/05/2015
  4552                              <1> 	; 28/04/2015
  4553                              <1> 	; 18/04/2015
  4554                              <1> 	; Get physical address
  4555                              <1> 	;     (allocates a new page for user if it is not present)
  4556                              <1> 	;	
  4557                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4558                              <1> 	; (buffer) address to physical address (of the buffer).)
  4559                              <1> 	; ('sys write', 'sys read' system calls...)
  4560                              <1> 	;
  4561                              <1> 	; INPUT ->
  4562                              <1> 	;	EBX = virtual address
  4563                              <1> 	;	u.pgdir = page directory (physical) address
  4564                              <1> 	;
  4565                              <1> 	; OUTPUT ->
  4566                              <1> 	;	EAX = physical address 
  4567                              <1> 	;	EBX = linear address	
  4568                              <1> 	;	EDX = physical address of the page frame
  4569                              <1> 	;	      (with attribute bits)
  4570                              <1> 	;	ECX = byte count within the page frame
  4571                              <1> 	;
  4572                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4573                              <1> 	;
  4574                              <1> 
  4575                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4576 000029ED A1[F1680000]        <1> 	mov	eax, [u.pgdir]
  4577                              <1> 
  4578                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4579                              <1> 	
  4580 000029F2 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4581                              <1> 	;
  4582                              <1> 	;mov	eax, [u.pgdir]
  4583 000029F8 E816FDFFFF          <1> 	call	get_pte
  4584                              <1> 		; EDX = Page table entry address (if CF=0)
  4585                              <1> 	        ;       Page directory entry address (if CF=1)
  4586                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4587                              <1> 		; EAX = Page table entry value (page address)
  4588                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4589 000029FD 731C                <1> 	jnc	short gpa_1
  4590                              <1> 	;
  4591 000029FF E8FDFBFFFF          <1> 	call	allocate_page
  4592 00002A04 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4593                              <1> gpa_0:
  4594 00002A06 E867FCFFFF          <1> 	call 	clear_page
  4595                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4596 00002A0B 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4597                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4598                              <1> 			   ; (user, writable, present page)	
  4599 00002A0D 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4600 00002A0F A1[F1680000]        <1> 	mov	eax, [u.pgdir]	
  4601 00002A14 E8FAFCFFFF          <1> 	call	get_pte
  4602 00002A19 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4603                              <1> gpa_1:
  4604                              <1> 	; EAX = PTE value, EDX = PTE address
  4605 00002A1B A801                <1> 	test 	al, PTE_A_PRESENT
  4606 00002A1D 750A                <1> 	jnz	short gpa_3
  4607 00002A1F 09C0                <1> 	or	eax, eax
  4608 00002A21 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4609                              <1> 
  4610                              <1> ; 24/12/2021
  4611                              <1> ; ('reload_page' procedure call is disabled)
  4612 00002A23 EB2C                <1> 	jmp	short gpa_im_err
  4613                              <1> 
  4614                              <1> 	; 20/07/2015
  4615                              <1> ;	push	ebp
  4616                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4617                              <1> ;	; reload swapped page
  4618                              <1> ;	call	reload_page ; 28/04/2015
  4619                              <1> ;	pop	ebp
  4620                              <1> ;	jc	short gpa_retn
  4621                              <1> gpa_2:
  4622                              <1> ; 24/12/2021
  4623                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4624                              <1> 
  4625                              <1> 	; 20/07/2015
  4626                              <1> 	; 20/05/2015
  4627                              <1> 	; add this page to swap queue
  4628                              <1> ;	push	eax 
  4629                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4630                              <1> ;	call 	add_to_swap_queue
  4631                              <1> ;	pop	eax
  4632                              <1> 		; PTE address in EDX
  4633                              <1> 		; virtual address in EBX
  4634                              <1> 	; EAX = memory page address
  4635 00002A25 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4636                              <1> 				  ; present flag, bit 0 = 1
  4637                              <1> 				  ; user flag, bit 2 = 1	
  4638                              <1> 				  ; writable flag, bit 1 = 1
  4639 00002A27 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4640                              <1> gpa_3:
  4641                              <1> 	; 18/10/2015
  4642 00002A29 89D9                <1> 	mov	ecx, ebx
  4643 00002A2B 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4644 00002A31 89C2                <1> 	mov 	edx, eax
  4645 00002A33 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4646 00002A37 01C8                <1> 	add	eax, ecx
  4647 00002A39 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4648 00002A3B 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4649 00002A41 F8                  <1> 	clc
  4650                              <1> gpa_retn:
  4651 00002A42 C3                  <1> 	retn	
  4652                              <1> gpa_4:	
  4653 00002A43 E8B9FBFFFF          <1> 	call	allocate_page
  4654 00002A48 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4655 00002A4A E823FCFFFF          <1> 	call	clear_page
  4656 00002A4F EBD4                <1> 	jmp	short gpa_2
  4657                              <1> 
  4658                              <1> gpa_im_err:	
  4659 00002A51 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4660                              <1> 				  ; Major error = 0 (No protection fault)	
  4661 00002A56 C3                  <1> 	retn
  4662                              <1> 
  4663                              <1> ; 24/12/2021
  4664                              <1> ; ('reload_page' procedure call is disabled)
  4665                              <1> 
  4666                              <1> ;reload_page:
  4667                              <1> 	; 20/07/2015
  4668                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4669                              <1> 	;
  4670                              <1> 	; Reload (Restore) swapped page at memory
  4671                              <1> 	;
  4672                              <1> 	; INPUT -> 
  4673                              <1> 	;	EBP = Virtual (linear) memory address
  4674                              <1> 	;	EAX = PTE value (swap disk sector address)
  4675                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4676                              <1> 	; OUTPUT ->
  4677                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4678                              <1> 	;
  4679                              <1> 	;	CF = 1 and EAX = error code
  4680                              <1> 	;
  4681                              <1> 	; Modified Registers -> none (except EAX)
  4682                              <1> 	;
  4683                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4684                              <1> ;	push	ebx      ;
  4685                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4686                              <1> ;	call	allocate_page
  4687                              <1> ;	jc	short rlp_im_err
  4688                              <1> ;	xchg 	eax, ebx	
  4689                              <1> ;	; EBX = Physical memory (page) address
  4690                              <1> ;	; EAX = Swap disk (offset) address
  4691                              <1> ;	; EBP = Virtual (linear) memory address
  4692                              <1> ;	call	swap_in
  4693                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4694                              <1> ;	mov	eax, ebx	
  4695                              <1> ;rlp_retn:
  4696                              <1> ;	pop	ebx
  4697                              <1> ;	retn
  4698                              <1> ;	
  4699                              <1> ;rlp_im_err:	
  4700                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4701                              <1> ;				  ; Major error = 0 (No protection fault)	
  4702                              <1> ;	jmp	short rlp_retn
  4703                              <1> ;
  4704                              <1> ;rlp_swp_err:
  4705                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4706                              <1> ;	jmp	short rlp_retn
  4707                              <1> 
  4708                              <1> copy_page_dir:
  4709                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4710                              <1> 	; 19/09/2015
  4711                              <1> 	; temporary - 07/09/2015
  4712                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4713                              <1> 	;
  4714                              <1> 	; INPUT -> 
  4715                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4716                              <1> 	;		    page directory.
  4717                              <1> 	; OUTPUT ->
  4718                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4719                              <1> 	;	       page directory.
  4720                              <1> 	;	(New page directory with new page table entries.)
  4721                              <1> 	;	(New page tables with read only copies of the parent's
  4722                              <1> 	;	pages.)
  4723                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4724                              <1> 	;
  4725                              <1> 	; Modified Registers -> none (except EAX)
  4726                              <1> 	;
  4727 00002A57 E8A5FBFFFF          <1> 	call	allocate_page
  4728 00002A5C 723E                <1> 	jc	short cpd_err
  4729                              <1> 	;
  4730 00002A5E 55                  <1> 	push	ebp ; 20/07/2015
  4731 00002A5F 56                  <1> 	push	esi
  4732 00002A60 57                  <1> 	push	edi
  4733 00002A61 53                  <1> 	push	ebx
  4734 00002A62 51                  <1> 	push	ecx
  4735 00002A63 8B35[F1680000]      <1> 	mov	esi, [u.pgdir]
  4736 00002A69 89C7                <1> 	mov	edi, eax
  4737 00002A6B 50                  <1> 	push	eax ; save child's page directory address
  4738                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4739                              <1> 	; (use same system space for all user page tables) 
  4740 00002A6C A5                  <1> 	movsd
  4741 00002A6D BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4742 00002A72 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4743                              <1> cpd_0:	
  4744 00002A77 AD                  <1> 	lodsd
  4745                              <1> 	;or	eax, eax
  4746                              <1>         ;jnz	short cpd_1
  4747 00002A78 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4748 00002A7A 7508                <1> 	jnz	short cpd_1
  4749                              <1>  	; (virtual address at the end of the page table)	
  4750 00002A7C 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4751 00002A82 EB0F                <1> 	jmp	short cpd_2
  4752                              <1> cpd_1:	
  4753 00002A84 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4754 00002A88 89C3                <1> 	mov	ebx, eax
  4755                              <1> 	; EBX = Parent's page table address
  4756 00002A8A E81F000000          <1> 	call	copy_page_table
  4757 00002A8F 720C                <1> 	jc	short cpd_p_err
  4758                              <1> 	; EAX = Child's page table address
  4759 00002A91 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4760                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4761                              <1> 			 ; (present, writable, user)
  4762                              <1> cpd_2:
  4763 00002A93 AB                  <1> 	stosd
  4764 00002A94 E2E1                <1> 	loop	cpd_0
  4765                              <1> 	;
  4766 00002A96 58                  <1> 	pop	eax  ; restore child's page directory address
  4767                              <1> cpd_3:
  4768 00002A97 59                  <1> 	pop	ecx
  4769 00002A98 5B                  <1> 	pop	ebx
  4770 00002A99 5F                  <1> 	pop	edi
  4771 00002A9A 5E                  <1> 	pop	esi
  4772 00002A9B 5D                  <1> 	pop	ebp
  4773                              <1> cpd_err:
  4774 00002A9C C3                  <1> 	retn
  4775                              <1> cpd_p_err:
  4776                              <1> 	; release the allocated pages missing (recover free space)
  4777 00002A9D 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4778 00002A9E 8B1D[F1680000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4779 00002AA4 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4780 00002AA9 29C0                <1> 	sub	eax, eax ; 0
  4781 00002AAB F9                  <1> 	stc
  4782 00002AAC EBE9                <1> 	jmp	short cpd_3	
  4783                              <1> 
  4784                              <1> copy_page_table:
  4785                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4786                              <1> 	; 19/09/2015
  4787                              <1> 	; temporary - 07/09/2015
  4788                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4789                              <1> 	;
  4790                              <1> 	; INPUT -> 
  4791                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4792                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4793                              <1> 	; OUTPUT ->
  4794                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4795                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4796                              <1> 	;	CF = 1 -> error 
  4797                              <1> 	;
  4798                              <1> 	; Modified Registers -> EBP (except EAX)
  4799                              <1> 	;
  4800 00002AAE E84EFBFFFF          <1> 	call	allocate_page
  4801 00002AB3 7244                <1> 	jc	short cpt_err
  4802                              <1> 	;
  4803 00002AB5 50                  <1> 	push	eax ; *
  4804                              <1> 	;push 	ebx
  4805 00002AB6 56                  <1> 	push	esi
  4806 00002AB7 57                  <1> 	push	edi
  4807 00002AB8 52                  <1> 	push	edx
  4808 00002AB9 51                  <1> 	push	ecx
  4809                              <1> 	;
  4810 00002ABA 89DE                <1> 	mov	esi, ebx
  4811 00002ABC 89C7                <1> 	mov	edi, eax
  4812 00002ABE 89C2                <1> 	mov	edx, eax
  4813 00002AC0 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4814                              <1> cpt_0:
  4815 00002AC6 AD                  <1> 	lodsd
  4816 00002AC7 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4817                              <1> 	;jnz	short cpt_1 (*)
  4818                              <1> 	; 24/12/2021
  4819                              <1> 	;and	eax, eax (*)
  4820 00002AC9 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4821                              <1> 	
  4822                              <1> ; 24/12/2021
  4823                              <1> ; ('reload_page' procedure call is disabled)
  4824                              <1> ;
  4825                              <1> ;	; ebp = virtual (linear) address of the memory page
  4826                              <1> ;	call	reload_page ; 28/04/2015
  4827                              <1> ;	jc	short cpt_p_err
  4828                              <1> cpt_1:
  4829 00002ACB 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4830 00002ACF 89C1                <1> 	mov	ecx, eax
  4831                              <1> 	; Allocate a new page for the child process
  4832 00002AD1 E82BFBFFFF          <1> 	call	allocate_page
  4833 00002AD6 721C                <1> 	jc	short cpt_p_err
  4834 00002AD8 57                  <1> 	push	edi
  4835 00002AD9 56                  <1> 	push	esi
  4836 00002ADA 89CE                <1> 	mov	esi, ecx
  4837 00002ADC 89C7                <1> 	mov	edi, eax
  4838 00002ADE B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4839 00002AE3 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4840 00002AE5 5E                  <1> 	pop	esi
  4841 00002AE6 5F                  <1> 	pop	edi
  4842                              <1> 	; 
  4843                              <1> ; 24/12/2021
  4844                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4845                              <1> ;
  4846                              <1> ;	push	ebx
  4847                              <1> ;	push	eax
  4848                              <1> ;	mov	ebx, ebp
  4849                              <1> ;	; ebx = virtual address of the memory page
  4850                              <1> ;	call	add_to_swap_queue
  4851                              <1> ;	pop	eax
  4852                              <1> ;	pop	ebx
  4853                              <1> 	;
  4854                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4855 00002AE7 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4856                              <1> cpt_2:
  4857 00002AE9 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4858                              <1> 	;
  4859 00002AEA 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4860                              <1> 	;
  4861 00002AF0 39D7                <1> 	cmp	edi, edx
  4862 00002AF2 72D2                <1> 	jb	short cpt_0
  4863                              <1> cpt_p_err:
  4864 00002AF4 59                  <1> 	pop	ecx
  4865 00002AF5 5A                  <1> 	pop	edx
  4866 00002AF6 5F                  <1> 	pop	edi
  4867 00002AF7 5E                  <1> 	pop	esi
  4868                              <1> 	;pop	ebx
  4869 00002AF8 58                  <1> 	pop	eax ; *
  4870                              <1> cpt_err:
  4871 00002AF9 C3                  <1> 	retn
  4872                              <1> 
  4873                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4874                              <1> 
  4875                              <1> ;; Data:
  4876                              <1> 
  4877                              <1> ; 09/03/2015
  4878                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4879                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4880                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4881                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4882                              <1> ;swpd_next:  dd 0 ; next free page block
  4883                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2103                                  %include 'sysdefs.inc' ; 09/03/2015
  2104                              <1> ; Retro UNIX 386 v1.1 Kernel (v0.2.1.4) - SYSDEFS.INC
  2105                              <1> ; Last Modification: 13/06/2022
  2106                              <1> ;
  2107                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2108                              <1> ; (Modified from 
  2109                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2110                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2111                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2112                              <1> ; ----------------------------------------------------------------------------
  2113                              <1> ;
  2114                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2115                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2116                              <1> ; <Bell Laboratories (17/3/1972)>
  2117                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2118                              <1> ;
  2119                              <1> ; ****************************************************************************
  2120                              <1> 
  2121                              <1> nproc 	equ	16  ; number of processes
  2122                              <1> nfiles 	equ	50
  2123                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2124                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2125                              <1> 
  2126                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2127                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2128                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2129                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2130                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2131                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2132                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2133                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2134                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2135                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2136                              <1> 	; '/core' dump file size = 32768 bytes
  2137                              <1>  
  2138                              <1> ; 08/03/2014 
  2139                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2140                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2141                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2142                              <1> 
  2143                              <1> ; 30/08/2013
  2144                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2145                              <1> 
  2146                              <1> ; 05/02/2014
  2147                              <1> ; process status
  2148                              <1> ;SFREE 	equ 0
  2149                              <1> ;SRUN	equ 1
  2150                              <1> ;SWAIT	equ 2
  2151                              <1> ;SZOMB	equ 3
  2152                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2153                              <1> 
  2154                              <1> ; 09/03/2015
  2155                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2156                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2157                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2158                              <1> 
  2159                              <1> ; 17/09/2015
  2160                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2161                              <1> 
  2162                              <1> ; 21/09/2015 (36) 
  2163                              <1> ; 01/07/2015 (35)
  2164                              <1> ; 14/07/2013 (0-34)
  2165                              <1> ; UNIX v1 system calls
  2166                              <1> _rele 	equ 0
  2167                              <1> _exit 	equ 1
  2168                              <1> _fork 	equ 2
  2169                              <1> _read 	equ 3
  2170                              <1> _write	equ 4
  2171                              <1> _open	equ 5
  2172                              <1> _close 	equ 6
  2173                              <1> _wait 	equ 7
  2174                              <1> _creat 	equ 8
  2175                              <1> _link 	equ 9
  2176                              <1> _unlink	equ 10
  2177                              <1> _exec	equ 11
  2178                              <1> _chdir	equ 12
  2179                              <1> _time 	equ 13
  2180                              <1> _mkdir 	equ 14
  2181                              <1> _chmod	equ 15
  2182                              <1> _chown	equ 16
  2183                              <1> _break	equ 17
  2184                              <1> _stat	equ 18
  2185                              <1> _seek	equ 19
  2186                              <1> _tell 	equ 20
  2187                              <1> _mount	equ 21
  2188                              <1> _umount	equ 22
  2189                              <1> _setuid	equ 23
  2190                              <1> _getuid	equ 24
  2191                              <1> _stime	equ 25
  2192                              <1> _quit	equ 26	
  2193                              <1> _intr	equ 27
  2194                              <1> _fstat	equ 28
  2195                              <1> _emt 	equ 29
  2196                              <1> _mdate 	equ 30
  2197                              <1> _stty 	equ 31
  2198                              <1> _gtty	equ 32
  2199                              <1> _ilgins	equ 33
  2200                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2201                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2202                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2203                              <1> 
  2204                              <1> %macro sys 1-4
  2205                              <1>     ; 13/04/2015
  2206                              <1>     ; Retro UNIX 386 v1 system call.		
  2207                              <1>     mov eax, %1
  2208                              <1>     %if %0 >= 2   
  2209                              <1>         mov ebx, %2
  2210                              <1>         %if %0 >= 3    
  2211                              <1>             mov ecx, %3
  2212                              <1>             %if %0 = 4
  2213                              <1>                mov edx, %4   
  2214                              <1>             %endif
  2215                              <1>         %endif
  2216                              <1>     %endif
  2217                              <1>     int 30h	   
  2218                              <1> %endmacro
  2219                              <1> 
  2220                              <1> ; 13/05/2015 - ERROR CODES
  2221                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2222                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2223                              <1> ; 14/05/2015
  2224                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2225                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2226                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2227                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2228                              <1> ; 16/05/2015		
  2229                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2230                              <1> ; 18/05/2015
  2231                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2232                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2233                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2234                              <1> ; 07/06/2015
  2235                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2236                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2237                              <1> ; 09/06/2015
  2238                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2239                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2240                              <1> ; 16/06/2015
  2241                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2242                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2243                              <1> ; 22/06/2015
  2244                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2245                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2246                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2247                              <1> ; 23/06/2015
  2248                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2249                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2250                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2251                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2252                              <1> ; 27/06/2015
  2253                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2254                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2255                              <1> ; 29/06/2015
  2256                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2257                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2258                              <1> ; 08/02/2022 
  2259                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2260                              <1> ; 10/10/2016
  2261                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2262                              <1> ; 18/05/2016
  2263                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2264                              <1> ; 15/10/2016
  2265                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2266                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2267                              <1> ; 16/10/2016
  2268                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2269                              <1> ; 08/02/2022
  2270                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2271                              <1> 
  2272                              <1> ; 13/06/2022
  2273                              <1> ; printer errors
  2274                              <1> ERR_PRN_NOT_RDY	   equ 15 ; 'device not ready !' error
  2275                              <1> ERR_PRN_TIMEOUT	   equ 25 ; 'time out !' error
  2276                              <1> ERR_PRN_PAPER	   equ 31 ; 'out of paper !' error
  2277                              <1> ERR_PRN_IO	   equ 32 ; 'io error !' error
  2278                              <1> ERR_PRN_BUSY	   equ 34 ; 'busy !' error
  2279                              <1> 
  2280                              <1> ; 26/08/2015
  2281                              <1> ; 24/07/2015
  2282                              <1> ; 24/06/2015
  2283                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2284                              <1> ; 01/07/2015
  2285                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2286                              <1> ; 24/12/2021
  2287                              <1> ERR_INV_FUNC	   equ 1  ; 'invalid system call !' error	 					 		
  2104                                  %include 'u0.s'        ; 15/03/2015
  2105                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS0.INC
  2106                              <1> ; Last Modification: 02/06/2022
  2107                              <1> ; ----------------------------------------------------------------------------
  2108                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2109                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2110                              <1> ;
  2111                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2112                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2113                              <1> ; <Bell Laboratories (17/3/1972)>
  2114                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2115                              <1> ;
  2116                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2117                              <1> ;
  2118                              <1> ; ****************************************************************************
  2119                              <1> 
  2120                              <1> sys_init:
  2121                              <1> 	; 26/02/2022
  2122                              <1> 	; 08/01/2022
  2123                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2124                              <1> 	; 18/10/2015
  2125                              <1> 	; 28/08/2015
  2126                              <1> 	; 24/08/2015
  2127                              <1> 	; 14/08/2015
  2128                              <1> 	; 24/07/2015 
  2129                              <1> 	; 02/07/2015
  2130                              <1> 	; 01/07/2015
  2131                              <1> 	; 23/06/2015
  2132                              <1> 	; 15/04/2015
  2133                              <1> 	; 13/03/2015
  2134                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2135                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2136                              <1> 	;
  2137                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2138                              <1> 	;
  2139                              <1> 	; 14/02/2014
  2140                              <1> 	; 14/07/2013
  2141                              <1> 	;;mov	ax, 41
  2142                              <1> 	; 24/12/2021
  2143                              <1> 	;xor	eax, eax
  2144                              <1> 	;mov	al, 41
  2145                              <1> 	;mov	[rootdir], ax
  2146                              <1> 	;mov	[u.cdir], ax
  2147                              <1> 	;;and	al, 1 ; 15/04/2015
  2148                              <1> 	;inc	al  ; ax = 1
  2149 00002AFA B001                <1> 	mov	al, 1
  2150 00002AFC A2[E7680000]        <1> 	mov	[u.uno], al
  2151                              <1> 	;mov	[mpid], ax
  2152                              <1> 	;mov	[p.pid], ax
  2153 00002B01 A2[84680000]        <1> 	mov	[mpid], al
  2154 00002B06 A2[B4650000]        <1> 	mov	[p.pid], al	
  2155 00002B0B A2[14660000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2156                              <1> 	; 24/12/2021
  2157 00002B10 B029                <1> 	mov	al, 41
  2158                              <1> 	;mov	[rootdir], ax
  2159                              <1> 	;mov	[u.cdir], ax
  2160 00002B12 A2[86680000]        <1> 	mov	[rootdir], al
  2161 00002B17 A2[9C680000]        <1> 	mov	[u.cdir], al
  2162                              <1> 	;
  2163 00002B1C B004                <1> 	mov	al, time_count ; 30/08/2013
  2164 00002B1E A2[DA680000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2165                              <1> 	; 02/07/2015
  2166 00002B23 A1[D8640000]        <1> 	mov	eax, [k_page_dir]
  2167                              <1> 	;sub	eax, eax
  2168 00002B28 A3[F1680000]        <1> 	mov	[u.pgdir], eax ; reset
  2169                              <1> 	; 18/10/2015
  2170                              <1> 	;mov	[u.ppgdir], eax ; 0
  2171                              <1> 	; 26/02/2022
  2172                              <1>  	;call	epoch
  2173                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2174                              <1> 	; 17/07/2013
  2175 00002B2D E884060000          <1> 	call 	bf_init ; buffer initialization
  2176                              <1> 	; 26/02/2022
  2177                              <1> 	; (save sysinit time on sb0)
  2178 00002B32 E829030000          <1> 	call	epoch
  2179 00002B37 A3[E4760000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2180                              <1> 	; 23/06/2015
  2181 00002B3C E8C0FAFFFF          <1> 	call	allocate_page
  2182                              <1> 	;;jc	error
  2183                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2184                              <1> 	; 24/12/2021
  2185 00002B41 7305                <1> 	jnc	short sysinit_1
  2186 00002B43 E989000000          <1> 	jmp	panic
  2187                              <1> sysinit_1:
  2188 00002B48 A3[E8680000]        <1> 	mov	[u.upage], eax ; user structure page	
  2189 00002B4D A3[24660000]        <1> 	mov	[p.upage], eax
  2190                              <1> 	;
  2191 00002B52 E81BFBFFFF          <1> 	call	clear_page
  2192                              <1> 	;
  2193                              <1> 	; 14/08/2015
  2194 00002B57 FA                  <1> 	cli
  2195                              <1> 	; 14/03/2015
  2196                              <1> 	; 17/01/2014
  2197 00002B58 E8D0010000          <1> 	call	sp_init ; serial port initialization
  2198                              <1> 	; 14/08/2015
  2199 00002B5D FB                  <1> 	sti
  2200                              <1> 	;
  2201                              <1> 	; 30/06/2015
  2202                              <1> 	;mov	esi, kernel_init_ok_msg
  2203                              <1> 	;call 	print_msg
  2204                              <1> 	;
  2205 00002B5E 30DB                <1> 	xor	bl, bl ; video page 0
  2206                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2207 00002B60 E8450F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2208 00002B65 FEC3                <1> 	inc	bl
  2209 00002B67 80FB08              <1> 	cmp	bl, 8
  2210 00002B6A 72F4                <1> 	jb	short vp_clr_nxt
  2211                              <1> 	;
  2212                              <1> 	; 24/07/2015
  2213                              <1> 	;push    KDATA
  2214                              <1>         ;push    esp
  2215                              <1> 	;mov	[tss.esp0], esp
  2216                              <1>         ;mov     word [tss.ss0], KDATA
  2217                              <1> 	;
  2218                              <1> 	; 08/01/2022
  2219                              <1> 	; 24/08/2015
  2220                              <1> 	;; temporary (01/07/2015)
  2221                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2222                              <1> 			       ; it is not needed here !
  2223                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2224 00002B6C FE0D[8D680000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2225                              <1> 			      ; 0 = executing a system call
  2226                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2227                              <1> 	;
  2228                              <1> 	;;; 06/08/2015
  2229                              <1> 	;;;call	getch ; wait for a key stroke
  2230                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2231                              <1> ;;sys_init_msg_wait:
  2232                              <1> ;;	push 	ecx
  2233                              <1> ;;	mov	al, 1
  2234                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2235                              <1> ;;	call	getc_n
  2236                              <1> ;;	pop	ecx
  2237                              <1> ;;	jnz	short sys_init_msg_ok
  2238                              <1> ;;	loop	sys_init_msg_wait
  2239                              <1> 	;
  2240                              <1> ;;sys_init_msg_ok:
  2241                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2242 00002B72 6A10                <1> 	push	KDATA ; ss
  2243 00002B74 54                  <1> 	push	esp
  2244 00002B75 9C                  <1> 	pushfd
  2245 00002B76 6A08                <1> 	push	KCODE ; cs
  2246 00002B78 68[A52B0000]        <1> 	push	init_exec ; eip
  2247 00002B7D 8925[90680000]      <1> 	mov	[u.sp], esp
  2248 00002B83 1E                  <1> 	push	ds
  2249 00002B84 06                  <1> 	push	es
  2250 00002B85 0FA0                <1> 	push	fs
  2251 00002B87 0FA8                <1> 	push	gs	
  2252 00002B89 60                  <1> 	pushad
  2253 00002B8A 8925[94680000]      <1> 	mov	[u.usp], esp
  2254 00002B90 E8B11B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2255                              <1> 		      ; and interrupt return components (for IRET)
  2256 00002B95 61                  <1> 	popad
  2257 00002B96 6658                <1> 	pop	ax ; gs
  2258 00002B98 6658                <1> 	pop	ax ; fs
  2259 00002B9A 6658                <1> 	pop	ax ; es
  2260 00002B9C 6658                <1> 	pop	ax ; ds	
  2261 00002B9E 58                  <1> 	pop	eax ; eip (init_exec)
  2262 00002B9F 6658                <1> 	pop	ax ; cs (KCODE)
  2263 00002BA1 58                  <1> 	pop	eax ; E-FLAGS
  2264 00002BA2 58                  <1> 	pop	eax ; esp
  2265 00002BA3 6658                <1> 	pop	ax ; ss (KDATA)
  2266                              <1> 	;
  2267                              <1> 	; 08/01/2022 ([u.ppgdir] is zero already)
  2268                              <1> 	;xor	eax, eax ; 0
  2269                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2270                              <1> 	;
  2271                              <1> 	; 02/07/2015
  2272                              <1> 	; [u.pgdir ] = [k_page_dir]
  2273                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2274                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2275                              <1> init_exec:
  2276                              <1> 	; 13/03/2013
  2277                              <1> 	; 24/07/2013
  2278 00002BA5 BB[C72B0000]        <1> 	mov	ebx, init_file
  2279 00002BAA B9[BF2B0000]        <1> 	mov	ecx, init_argp
  2280                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2281                              <1> 	; ECX contains address of argument list pointer
  2282                              <1> 	;
  2283                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2284                              <1> 			      ; 0 = executing a system call
  2285                              <1> 	sys	_exec  ; execute file
  2205                              <2> 
  2206                              <2> 
  2207 00002BAF B80B000000          <2>  mov eax, %1
  2208                              <2>  %if %0 >= 2
  2209                              <2>  mov ebx, %2
  2210                              <2>  %if %0 >= 3
  2211                              <2>  mov ecx, %3
  2212                              <2>  %if %0 = 4
  2213                              <2>  mov edx, %4
  2214                              <2>  %endif
  2215                              <2>  %endif
  2216                              <2>  %endif
  2217 00002BB4 CD30                <2>  int 30h
  2286 00002BB6 7319                <1> 	jnc	short panic
  2287                              <1> 	;
  2288 00002BB8 BE[EC610000]        <1> 	mov	esi, etc_init_err_msg
  2289                              <1> 	; 08/01/2022
  2290                              <1> 	;call 	print_msg
  2291 00002BBD EB17                <1> 	jmp	short key_to_reboot
  2292                              <1> 
  2293                              <1> ;align 4
  2294                              <1> init_argp:
  2295 00002BBF [C72B0000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2296                              <1> init_file:
  2297                              <1> 	; 24/08/2015
  2298 00002BC7 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2298 00002BD0 00                  <1>
  2299                              <1> panic:
  2300                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2301                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2302 00002BD1 BE[D1610000]        <1> 	mov 	esi, panic_msg
  2303                              <1> key_to_reboot: ; 08/01/2022 (Retro UNIX 386 v1.1)
  2304 00002BD6 E819000000          <1> 	call 	print_msg
  2305                              <1> ;key_to_reboot:
  2306                              <1> 	; 15/11/2015
  2307 00002BDB E8162D0000          <1> 	call 	getch 
  2308                              <1> 		; wait for a character from the current tty
  2309                              <1> 	;
  2310 00002BE0 B00A                <1> 	mov	al, 0Ah
  2311 00002BE2 8A1D[06650000]      <1> 	mov	bl, [ptty] ; [active_page]
  2312 00002BE8 B407                <1> 	mov	ah, 07h ; Black background, 
  2313                              <1> 			; light gray forecolor
  2314 00002BEA E8D2E7FFFF          <1> 	call 	write_tty
  2315 00002BEF E971E4FFFF          <1> 	jmp	cpu_reset 
  2316                              <1> 
  2317                              <1> print_msg:
  2318                              <1> 	; 01/07/2015
  2319                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2320                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2321                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2322                              <1> 	;
  2323                              <1> 	;
  2324 00002BF4 AC                  <1> 	lodsb
  2325                              <1> pmsg1:
  2326 00002BF5 56                  <1> 	push 	esi
  2327 00002BF6 0FB61D[06650000]    <1> 	movzx	ebx, byte [ptty]
  2328 00002BFD B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2329 00002BFF E8BDE7FFFF          <1> 	call 	write_tty
  2330 00002C04 5E                  <1> 	pop	esi
  2331 00002C05 AC                  <1> 	lodsb
  2332 00002C06 20C0                <1> 	and 	al, al
  2333 00002C08 75EB                <1> 	jnz 	short pmsg1
  2334 00002C0A C3                  <1> 	retn
  2335                              <1> 	
  2336                              <1> ctrlbrk:
  2337                              <1> 	; 04/02/2022
  2338                              <1> 	; 01/02/2022
  2339                              <1> 	; 12/11/2015
  2340                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2341                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2342                              <1> 	;
  2343                              <1> 	; INT 1Bh (control+break) handler
  2344                              <1> 	;
  2345                              <1>       	; Retro Unix 8086 v1 feature only!
  2346                              <1>       	;
  2347 00002C0B 66833D[DC680000]00  <1> 	cmp 	word [u.intr], 0
  2348 00002C13 764B                <1> 	jna 	short cbrk4
  2349                              <1> cbrk0:
  2350                              <1> 	; 12/11/2015
  2351                              <1> 	; 06/12/2013
  2352 00002C15 66833D[DE680000]00  <1> 	cmp 	word [u.quit], 0
  2353 00002C1D 7441                <1> 	jz	short cbrk4
  2354                              <1> 	;
  2355                              <1> 	; 20/09/2013	
  2356                              <1> 	;push 	ax
  2357                              <1> 	; 01/02/2022
  2358 00002C1F 50                  <1> 	push	eax
  2359                              <1> 
  2360                              <1> 	; 04/02/2022
  2361                              <1> 	; (repetitive ctrl+brk check) 
  2362 00002C20 66A1[DE680000]      <1> 	mov	ax, [u.quit]
  2363 00002C26 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2364 00002C28 7435                <1> 	jz	short cbrk3
  2365                              <1> 
  2366                              <1> 	; 20/09/2013
  2367 00002C2A A0[06650000]        <1> 	mov	al, [ptty]
  2368                              <1> 	;
  2369                              <1> 	; 12/11/2015
  2370                              <1> 	;
  2371                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2372                              <1> 	; or ctrl+break from console (pseudo) tty
  2373                              <1> 	; (!redirection!)
  2374                              <1> 	;
  2375 00002C2F 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2376 00002C31 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2377                              <1> 	;	
  2378                              <1> 	; Serial port interrupt handler sets [ptty]
  2379                              <1> 	; to the port's tty number (as temporary).
  2380                              <1> 	;
  2381                              <1> 	; If active process is using a stdin or 
  2382                              <1> 	; stdout redirection (by the shell),
  2383                              <1>         ; console tty keyboard must be available
  2384                              <1> 	; to terminate running process,
  2385                              <1> 	; in order to prevent a deadlock. 
  2386                              <1> 	;
  2387 00002C33 52                  <1> 	push	edx
  2388 00002C34 0FB615[E7680000]    <1> 	movzx	edx, byte [u.uno]
  2389 00002C3B 3A82[F3650000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2390 00002C41 5A                  <1> 	pop	edx
  2391 00002C42 7412                <1> 	je	short cbrk2
  2392                              <1> cbrk1:
  2393 00002C44 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2394                              <1> 	; 06/12/2013
  2395 00002C46 3A05[C8680000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2396 00002C4C 7408                <1> 	je	short cbrk2	
  2397 00002C4E 3A05[C9680000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2398 00002C54 7509                <1> 	jne	short cbrk3	
  2399                              <1> cbrk2:
  2400                              <1> 	;; 06/12/2013
  2401                              <1> 	;mov	ax, [u.quit]
  2402                              <1> 	;and	ax, ax
  2403                              <1> 	;jz	short cbrk3
  2404                              <1> 	;
  2405                              <1> 	;xor	ax, ax ; 0
  2406                              <1> 	;dec	ax
  2407                              <1> 	; 01/02/2022
  2408 00002C56 31C0                <1> 	xor	eax, eax ; 0
  2409 00002C58 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2410                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2411 00002C59 66A3[DE680000]      <1> 	mov	[u.quit], ax
  2412                              <1> cbrk3:
  2413                              <1> 	;pop	ax
  2414                              <1> 	; 01/02/2022
  2415 00002C5F 58                  <1> 	pop	eax
  2416                              <1> cbrk4:
  2417 00002C60 C3                  <1> 	retn
  2418                              <1> 
  2419                              <1> com2_int:
  2420                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2421                              <1> 	; 07/11/2015 
  2422                              <1> 	; 24/10/2015
  2423                              <1> 	; 23/10/2015
  2424                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2425                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2426                              <1> 	; < serial port 2 interrupt handler >
  2427                              <1> 	;
  2428 00002C61 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2429                              <1> 	;;push	eax
  2430                              <1> 	; 08/01/2022
  2431 00002C64 29C0                <1> 	sub	eax, eax
  2432 00002C66 B009                <1> 	mov	al, 9
  2433                              <1> 	;mov	ax, 9
  2434 00002C68 EB07                <1> 	jmp	short comm_int
  2435                              <1> com1_int:
  2436                              <1> 	; 07/11/2015
  2437                              <1> 	; 24/10/2015
  2438 00002C6A 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2439                              <1> 	; 23/10/2015
  2440                              <1> 	;push	eax
  2441                              <1> 	; 08/01/2022
  2442 00002C6D 29C0                <1> 	sub	eax, eax
  2443 00002C6F B008                <1> 	mov	al, 8
  2444                              <1> 	;mov	ax, 8
  2445                              <1> comm_int:
  2446                              <1> 	; 08/01/2022
  2447                              <1> 	; 20/11/2015
  2448                              <1> 	; 18/11/2015
  2449                              <1> 	; 17/11/2015
  2450                              <1> 	; 16/11/2015
  2451                              <1> 	; 09/11/2015
  2452                              <1> 	; 08/11/2015
  2453                              <1> 	; 07/11/2015
  2454                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2455                              <1> 	; 01/11/2015
  2456                              <1> 	; 26/10/2015
  2457                              <1> 	; 23/10/2015
  2458 00002C71 53                  <1> 	push	ebx
  2459 00002C72 56                  <1> 	push	esi
  2460 00002C73 57                  <1> 	push	edi
  2461 00002C74 1E                  <1> 	push 	ds
  2462 00002C75 06                  <1> 	push 	es
  2463                              <1> 	; 18/11/2015
  2464 00002C76 0F20DB              <1> 	mov	ebx, cr3
  2465 00002C79 53                  <1> 	push	ebx ; ****
  2466                              <1> 	;
  2467 00002C7A 51                  <1> 	push	ecx ; ***
  2468 00002C7B 52                  <1> 	push	edx ; **
  2469                              <1> 	;
  2470 00002C7C BB10000000          <1> 	mov	ebx, KDATA
  2471 00002C81 8EDB                <1> 	mov	ds, bx
  2472 00002C83 8EC3                <1> 	mov	es, bx
  2473                              <1> 	;
  2474 00002C85 8B0D[D8640000]      <1> 	mov	ecx, [k_page_dir]
  2475 00002C8B 0F22D9              <1> 	mov	cr3, ecx
  2476                              <1> 	; 20/11/2015
  2477                              <1> 	; Interrupt identification register
  2478 00002C8E 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2479                              <1> 	;
  2480 00002C92 3C08                <1> 	cmp 	al, 8 
  2481 00002C94 7702                <1> 	ja 	short com_i0
  2482                              <1> 	;
  2483                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2484                              <1> 	; 20/11/2015
  2485                              <1> 	; 17/11/2015
  2486                              <1> 	; 16/11/2015
  2487                              <1> 	; 15/11/2015
  2488                              <1> 	; 24/10/2015
  2489                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2490                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2491                              <1> 	; < serial port 1 interrupt handler >
  2492                              <1> 	;
  2493 00002C96 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2494                              <1> com_i0:
  2495                              <1> 	;push	eax ; *
  2496                              <1> 	; 07/11/2015
  2497 00002C98 A2[46650000]        <1> 	mov 	byte [ccomport], al
  2498                              <1> 	; 09/11/2015
  2499                              <1> 	;movzx	ebx, ax ; 8 or 9
  2500                              <1> 	; 08/01/2022
  2501 00002C9D 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2502                              <1> 	; 17/11/2015
  2503                              <1>  	; reset request for response status
  2504 00002C9F 88A3[3C650000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2505                              <1> 	;
  2506                              <1> 	; 20/11/2015
  2507 00002CA5 EC                  <1> 	in	al, dx		; read interrupt id. register
  2508 00002CA6 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2509 00002CA8 2404                <1> 	and	al, 4		; received data available?	
  2510 00002CAA 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2511                              <1> 	;
  2512                              <1> 	; 20/11/2015
  2513 00002CAC 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2514 00002CAF EC                  <1> 	in	al, dx     	; read character
  2515                              <1> 	;JMP	$+2	   	; I/O DELAY
  2516                              <1> 	; 08/11/2015
  2517                              <1> 	; 07/11/2015
  2518 00002CB0 89DE                <1> 	mov	esi, ebx 
  2519 00002CB2 89DF                <1> 	mov	edi, ebx
  2520 00002CB4 81C6[40650000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2521 00002CBA 81C7[42650000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2522 00002CC0 8806                <1> 	mov	[esi], al ; received char (current char)
  2523                              <1> 	; query
  2524 00002CC2 20C0                <1> 	and	al, al
  2525 00002CC4 7527                <1> 	jnz	short com_i2
  2526                              <1>    	; response
  2527                              <1> 	; 17/11/2015
  2528                              <1> 	; set request for response status
  2529 00002CC6 FE83[3C650000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2530                              <1> 	;
  2531 00002CCC 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2532 00002CD0 EC                  <1> 	in	al, dx	   	; read line status register 
  2533 00002CD1 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2534 00002CD3 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2535 00002CD5 7445                <1> 	jz	short com_eoi 	; no
  2536 00002CD7 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2537 00002CD9 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2538 00002CDD EE                  <1> 	out	dx, al	   	; send on serial port
  2539                              <1> 	; 17/11/2015
  2540 00002CDE 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2541 00002CE1 7502                <1> 	jne 	short com_i1    ; no
  2542 00002CE3 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2543                              <1> com_i1:
  2544                              <1> 	; 17/11/2015
  2545                              <1> 	; reset request for response status (again)
  2546 00002CE5 FE8B[3C650000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2547 00002CEB EB2F                <1> 	jmp	short com_eoi
  2548                              <1> com_i2:	
  2549                              <1> 	; 08/11/2015
  2550 00002CED 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2551 00002CEF 7417                <1> 	je	short com_i3	; (check for response signal)
  2552                              <1> 	; 07/11/2015
  2553 00002CF1 3C04                <1> 	cmp	al, 04h	; EOT
  2554 00002CF3 751C                <1> 	jne	short com_i4	
  2555                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2556                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2557                              <1> 	; 08/11/2015
  2558                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2559 00002CF5 861D[06650000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2560 00002CFB E80BFFFFFF          <1> 	call 	ctrlbrk
  2561 00002D00 861D[06650000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2562                              <1> 	;mov	al, 04h ; EOT
  2563                              <1> 	; 08/11/2015
  2564 00002D06 EB09                <1> 	jmp	short com_i4	
  2565                              <1> com_i3:
  2566                              <1> 	; 08/11/2015
  2567                              <1> 	; If 0FFh has been received just after a query
  2568                              <1> 	; (schar, ZERO), it is a response signal.
  2569                              <1> 	; 17/11/2015
  2570 00002D08 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2571 00002D0B 7704                <1> 	ja	short com_i4 ; no
  2572                              <1> 	; reset query status (schar)
  2573 00002D0D 8807                <1> 	mov	[edi], al ; 0FFh
  2574 00002D0F FEC0                <1> 	inc	al ; 0
  2575                              <1> com_i4:
  2576                              <1> 	; 27/07/2014
  2577                              <1> 	; 09/07/2014
  2578 00002D11 D0E3                <1> 	shl	bl, 1	
  2579 00002D13 81C3[08650000]      <1> 	add	ebx, ttychr
  2580                              <1> 	; 23/07/2014 (always overwrite)
  2581                              <1> 	;;cmp	word [ebx], 0
  2582                              <1> 	;;ja	short com_eoi
  2583                              <1> 	;
  2584 00002D19 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2585                              <1> 			    ; scan code = 0
  2586                              <1> com_eoi:
  2587                              <1> 	;mov	al, 20h
  2588                              <1> 	;out	20h, al	   ; end of interrupt
  2589                              <1> 	;
  2590                              <1> 	; 07/11/2015
  2591                              <1>       	;pop	eax ; *
  2592 00002D1C A0[46650000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2593                              <1> 	; al = tty number (8 or 9)
  2594 00002D21 E8FA1A0000          <1>         call	wakeup
  2595                              <1> com_iret:
  2596                              <1> 	; 23/10/2015
  2597 00002D26 5A                  <1> 	pop	edx ; **
  2598 00002D27 59                  <1> 	pop	ecx ; ***
  2599                              <1> 	; 18/11/2015
  2600                              <1> 	;pop	eax ; ****
  2601                              <1> 	;mov	cr3, eax
  2602                              <1> 	;jmp	iiret
  2603 00002D28 E976DCFFFF          <1> 	jmp	iiretp
  2604                              <1> 
  2605                              <1> ;iiretp: ; 01/09/2015
  2606                              <1> ;	; 28/08/2015
  2607                              <1> ;	pop	eax ; (*) page directory
  2608                              <1> ;	mov	cr3, eax
  2609                              <1> ;iiret:
  2610                              <1> ;	; 22/08/2014
  2611                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2612                              <1> ;	out	20h, al	; 8259 PORT
  2613                              <1> ;	;
  2614                              <1> ;	pop	es
  2615                              <1> ;	pop	ds
  2616                              <1> ;	pop	edi
  2617                              <1> ;	pop	esi
  2618                              <1> ;	pop	ebx ; 29/08/2014
  2619                              <1> ;	pop 	eax
  2620                              <1> ;	iretd
  2621                              <1> 
  2622                              <1> sp_init:
  2623                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2624                              <1> 	; 07/11/2015
  2625                              <1> 	; 29/10/2015
  2626                              <1> 	; 26/10/2015
  2627                              <1> 	; 23/10/2015
  2628                              <1> 	; 29/06/2015
  2629                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2630                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2631                              <1> 	; Initialization of Serial Port Communication Parameters
  2632                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2633                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2634                              <1> 	;
  2635                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2636                              <1> 	;
  2637                              <1> 	; INPUT:  (29/06/2015)
  2638                              <1> 	;	AL = 0 for COM1
  2639                              <1> 	;	     1 for COM2
  2640                              <1> 	;	AH = Communication parameters	
  2641                              <1> 	;
  2642                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2643                              <1> 	;	Bit	4	3	2	1	0
  2644                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2645                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2646                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2647                              <1> 	;		11 = even
  2648                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2649                              <1> 	;		Retro UNIX 386 v1 feature only !
  2650                              <1> 	;	Bit	7    6    5  | Baud rate
  2651                              <1> 	;		------------------------
  2652                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2653                              <1> 	;		0    0    1  | 9600 (12)
  2654                              <1> 	;		0    1    0  | 19200 (6) 
  2655                              <1> 	;		0    1	  1  | 38400 (3) 
  2656                              <1> 	;		1    0	  0  | 14400 (8)
  2657                              <1> 	;		1    0	  1  | 28800 (4)
  2658                              <1> 	;		1    1    0  | 57600 (2)
  2659                              <1> 	;		1    1    1  | 115200 (1) 	
  2660                              <1> 	
  2661                              <1> 	; References:	
  2662                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2663                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2664                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2665                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2666                              <1> 	;
  2667                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2668                              <1> 	;
  2669 00002D2D BB[42650000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2670 00002D32 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2671                              <1> 	; 29/10/2015
  2672 00002D36 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2673 00002D3A E84F000000          <1> 	call	sp_i3	; call A4	
  2674 00002D3F A880                <1> 	test	al, 80h
  2675 00002D41 740E                <1> 	jz	short sp_i0 ; OK..
  2676                              <1> 		; Error !
  2677                              <1> 	;mov	dx, 3F8h
  2678 00002D43 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2679                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2680                              <1> 	; 08/01/2022
  2681 00002D46 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2682 00002D48 E841000000          <1> 	call	sp_i3	; call A4	
  2683 00002D4D A880                <1> 	test	al, 80h
  2684 00002D4F 7508                <1> 	jnz	short sp_i1
  2685                              <1> sp_i0:
  2686                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2687                              <1>         ; (INT 14h initialization code disables interrupts.)
  2688                              <1> 	;
  2689 00002D51 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2690 00002D54 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2691                              <1> sp_i1:
  2692 00002D59 43                  <1> 	inc	ebx
  2693 00002D5A 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2694                              <1> 	; 29/10/2015
  2695                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2696                              <1> 	; 08/01/2022
  2697 00002D5E B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2698 00002D60 E829000000          <1> 	call	sp_i3	; call A4	
  2699 00002D65 A880                <1> 	test	al, 80h
  2700 00002D67 740E                <1> 	jz	short sp_i2 ; OK..
  2701                              <1> 		; Error !
  2702                              <1> 	;mov	dx, 2F8h
  2703 00002D69 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2704                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2705                              <1> 	; 08/01/2022
  2706 00002D6C B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2707 00002D6E E81B000000          <1> 	call	sp_i3	; call A4	
  2708 00002D73 A880                <1> 	test	al, 80h
  2709 00002D75 7516                <1> 	jnz	short sp_i7
  2710                              <1> sp_i2:
  2711 00002D77 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2712                              <1> sp_i6:
  2713                              <1> 	;; COM2 - enabling IRQ 3
  2714                              <1> 	; 08/01/2022
  2715 00002D7A B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2716                              <1> 	; 07/11/2015
  2717                              <1> 	; 26/10/2015
  2718                              <1> 	;pushf
  2719                              <1> 	;cli
  2720                              <1> 	;;
  2721                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2722                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2723                              <1> 	;in	al, dx 	   		; read register
  2724                              <1> 	;JMP	$+2	   		; I/O DELAY
  2725                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2726                              <1> 	;out	dx, al     		; write back to register
  2727                              <1> 	;JMP	$+2	   		; I/O DELAY
  2728                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2729                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2730                              <1> 	;in	al, dx     		; read register
  2731                              <1> 	;JMP	$+2	   		; I/O DELAY
  2732                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2733                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2734                              <1> 	;out	dx, al 	   		; write back to register
  2735                              <1> 	;JMP	$+2        		; I/O DELAY
  2736                              <1> 	;in	al, 21h    		; read interrupt mask register
  2737                              <1> 	;JMP	$+2	   		; I/O DELAY
  2738                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2739                              <1> 	;out	21h, al    		; write back to register
  2740                              <1> 	;
  2741                              <1> 	; 08/01/2022
  2742 00002D7C 9C                  <1> 	pushf
  2743 00002D7D E8AA000000          <1> 	call	sp_i8
  2744                              <1> 	; 23/10/2015
  2745 00002D82 B8[612C0000]        <1> 	mov 	eax, com2_int
  2746 00002D87 A3[15320000]        <1> 	mov	[com2_irq3], eax
  2747                              <1> 	; 26/10/2015
  2748 00002D8C 9D                  <1> 	popf	
  2749                              <1> sp_i7:
  2750 00002D8D C3                  <1> 	retn
  2751                              <1> 
  2752                              <1> sp_i3:
  2753                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2754                              <1> 	; 28/10/2015
  2755 00002D8E FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2756 00002D90 B000                <1> 	mov	al, 0
  2757 00002D92 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2758 00002D93 EB00                <1> 	JMP	$+2			; I/O DELAY
  2759 00002D95 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2760 00002D98 B080                <1> 	mov	al, 80h			
  2761 00002D9A EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2762                              <1> 	;-----	SET BAUD RATE DIVISOR
  2763                              <1> 	; 26/10/2015
  2764 00002D9B 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2765                              <1> 					; of the divisor value
  2766 00002D9E 88C8                <1> 	mov	al, cl	; 1
  2767 00002DA0 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2768                              <1> 					; 2 = 57600 baud
  2769                              <1> 					; 3 = 38400 baud
  2770                              <1> 					; 6 = 19200 baud
  2771                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2772 00002DA1 EB00                <1> 	JMP	$+2			; I/O DELAY
  2773 00002DA3 28C0                <1> 	sub	al, al
  2774 00002DA5 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2775                              <1> 					; of the divisor value
  2776 00002DA7 EE                  <1> 	out	dx, al ; 0
  2777 00002DA8 EB00                <1> 	JMP	$+2			; I/O DELAY
  2778                              <1> 	;	
  2779 00002DAA 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2780                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2781 00002DAC 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2782 00002DAF EE                  <1> 	out	dx, al			
  2783 00002DB0 EB00                <1> 	JMP	$+2			; I/O DELAY
  2784                              <1> 	; 29/10/2015
  2785 00002DB2 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2786 00002DB4 30C0                <1> 	xor	al, al			; 0
  2787 00002DB6 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2788 00002DB7 EB00                <1> 	JMP	$+2	
  2789                              <1> sp_i4:
  2790                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2791                              <1> 	; 29/06/2015 (line status after modem status)
  2792 00002DB9 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2793                              <1> sp_i4s:
  2794 00002DBC EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2795 00002DBD EB00                <1> 	JMP	$+2			; I/O DELAY
  2796 00002DBF 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2797 00002DC1 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2798                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2799 00002DC3 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2800                              <1> 	; AL = Line status, AH = Modem status
  2801 00002DC4 C3                  <1> 	retn
  2802                              <1> 
  2803                              <1> sp_status:
  2804                              <1> 	; 29/06/2015
  2805                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2806                              <1> 	; Get serial port status
  2807 00002DC5 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2808 00002DC9 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2809                              <1> 					; dx = 2FEh for COM2
  2810 00002DCB EBEF                <1> 	jmp	short sp_i4s
  2811                              <1> 
  2812                              <1> sp_setp: ; Set serial port communication parameters
  2813                              <1> 	; 08/01/2022
  2814                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2815                              <1> 	; 07/11/2015
  2816                              <1> 	; 29/10/2015
  2817                              <1> 	; 29/06/2015
  2818                              <1> 	; Retro UNIX 386 v1 feature only !	
  2819                              <1> 	;
  2820                              <1> 	; INPUT:
  2821                              <1> 	;	AL = 0 for COM1
  2822                              <1> 	;	     1 for COM2
  2823                              <1> 	;	AH = Communication parameters (*)
  2824                              <1> 	; OUTPUT:
  2825                              <1> 	;	CL = Line status
  2826                              <1> 	;	CH = Modem status
  2827                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2828                              <1> 	;		 'invalid parameter !' 
  2829                              <1> 	;		 	 or
  2830                              <1> 	;		 'device not ready !' error
  2831                              <1> 	;	
  2832                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2833                              <1> 	;	Bit	4	3	2	1	0
  2834                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2835                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2836                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2837                              <1> 	;		11 = even
  2838                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2839                              <1> 	;		Retro UNIX 386 v1 feature only !
  2840                              <1> 	;	Bit	7    6    5  | Baud rate
  2841                              <1> 	;		------------------------
  2842                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2843                              <1> 	;		0    0    1  | 9600 (12)
  2844                              <1> 	;		0    1    0  | 19200 (6) 
  2845                              <1> 	;		0    1	  1  | 38400 (3) 
  2846                              <1> 	;		1    0	  0  | 14400 (8)
  2847                              <1> 	;		1    0	  1  | 28800 (4)
  2848                              <1> 	;		1    1    0  | 57600 (2)
  2849                              <1> 	;		1    1    1  | 115200 (1) 
  2850                              <1> 	;
  2851                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2852                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2853                              <1> 	;
  2854                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2855                              <1> 	;
  2856 00002DCD 66BAF803            <1> 	mov	dx, 3F8h
  2857 00002DD1 BB[42650000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2858 00002DD6 3C01                <1> 	cmp	al, 1
  2859 00002DD8 7770                <1> 	ja 	short sp_invp_err
  2860 00002DDA 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2861 00002DDC FECE                <1> 	dec	dh ; 2F8h
  2862 00002DDE 43                  <1> 	inc	ebx ; COM2 control byte offset
  2863                              <1> sp_setp1:
  2864                              <1> 	; 29/10/2015
  2865 00002DDF 8823                <1> 	mov	[ebx], ah
  2866 00002DE1 0FB6CC              <1> 	movzx 	ecx, ah
  2867 00002DE4 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2868 00002DE7 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2869 00002DEA 8A81[592E0000]      <1> 	mov	al, [ecx+b_div_tbl]
  2870 00002DF0 6689C1              <1> 	mov	cx, ax
  2871 00002DF3 E896FFFFFF          <1> 	call	sp_i3
  2872 00002DF8 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2873 00002DFB A880                <1> 	test	al, 80h
  2874 00002DFD 740F                <1> 	jz	short sp_setp2
  2875 00002DFF C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2876                              <1> stp_dnr_err:
  2877 00002E02 C705[ED680000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2877 00002E0A 0000                <1>
  2878                              <1> 	; CL = Line status, CH = Modem status
  2879 00002E0C F9                  <1> 	stc
  2880 00002E0D C3                  <1> 	retn
  2881                              <1> sp_setp2:
  2882 00002E0E 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2883                              <1>         ;jna	sp_i6
  2884                              <1> 		      ; COM1 (3F?h)
  2885                              <1> 	; 24/12/2021
  2886 00002E11 7705                <1> 	ja	short sp_i5
  2887 00002E13 E962FFFFFF          <1> 	jmp	sp_i6
  2888                              <1> sp_i5: 
  2889                              <1> 	; 08/01/2022
  2890 00002E18 B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2891                              <1> 	; 07/11/2015
  2892                              <1> 	; 26/10/2015
  2893                              <1> 	; 29/06/2015
  2894                              <1> 	;
  2895                              <1> 	;; COM1 - enabling IRQ 4
  2896                              <1> 	;pushf
  2897                              <1> 	;cli
  2898                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2899                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2900                              <1> 	;in	al, dx 	   		; read register
  2901                              <1> 	;JMP	$+2			; I/O DELAY
  2902                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2903                              <1> 	;out	dx, al     		; write back to register
  2904                              <1> 	;JMP	$+2			; I/O DELAY
  2905                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2906                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2907                              <1> 	;in	al, dx     		; read register
  2908                              <1> 	;JMP	$+2			; I/O DELAY
  2909                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2910                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2911                              <1> 	;out	dx, al 	   		; write back to register
  2912                              <1> 	;JMP	$+2        		; I/O DELAY
  2913                              <1> 	;in	al, 21h    		; read interrupt mask register
  2914                              <1> 	;JMP	$+2			; I/O DELAY
  2915                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2916                              <1> 	;out	21h, al    		; write back to register
  2917                              <1> 	;
  2918                              <1> 	; 08/01/2022
  2919 00002E1A 9C                  <1> 	pushf
  2920 00002E1B E80C000000          <1> 	call	sp_i8
  2921                              <1> 	; 23/10/2015
  2922 00002E20 B8[6A2C0000]        <1> 	mov 	eax, com1_int
  2923 00002E25 A3[11320000]        <1> 	mov	[com1_irq4], eax
  2924                              <1> 	; 26/10/2015
  2925 00002E2A 9D                  <1> 	popf
  2926 00002E2B C3                  <1> 	retn
  2927                              <1> 
  2928                              <1> sp_i8:
  2929                              <1> 	; 08/01/2022
  2930                              <1> 	;pushf
  2931 00002E2C FA                  <1> 	cli
  2932                              <1> 	;
  2933                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2934 00002E2D B2FC                <1> 	mov	dl, 0FCh
  2935 00002E2F EC                  <1> 	in	al, dx 	   		; read register
  2936 00002E30 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2937 00002E32 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2938 00002E34 EE                  <1> 	out	dx, al     		; write back to register
  2939 00002E35 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2940                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2941 00002E37 B2F9                <1> 	mov	dl, 0F9h
  2942 00002E39 EC                  <1> 	in	al, dx     		; read register
  2943 00002E3A EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2944                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2945 00002E3C 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2946 00002E3E EE                  <1> 	out	dx, al 	   		; write back to register
  2947 00002E3F EB00                <1> 	JMP	$+2        		; I/O DELAY
  2948 00002E41 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2949 00002E43 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2950                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2951 00002E45 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2952 00002E47 E621                <1> 	out	21h, al    		; write back to register
  2953                              <1> 	;
  2954                              <1> 	;popf	
  2955 00002E49 C3                  <1> 	retn
  2956                              <1> 
  2957                              <1> sp_invp_err:
  2958 00002E4A C705[ED680000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2958 00002E52 0000                <1>
  2959 00002E54 31C9                <1> 	xor	ecx, ecx
  2960 00002E56 49                  <1> 	dec	ecx ; 0FFFFh
  2961 00002E57 F9                  <1> 	stc
  2962 00002E58 C3                  <1> 	retn
  2963                              <1> 
  2964                              <1> ; 29/10/2015
  2965                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2966 00002E59 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2967                              <1> 
  2968                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2969                              <1> epoch:
  2970                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2971                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2972                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2973                              <1> 	; 'epoch' procedure prototype: 
  2974                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2975                              <1> 	; 14/11/2012
  2976                              <1> 	; unixboot.asm (boot file configuration)
  2977                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2978                              <1> 	; 21/7/2012
  2979                              <1> 	; 15/7/2012
  2980                              <1> 	; 14/7/2012		
  2981                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2982                              <1> 	; compute current date and time as UNIX Epoch/Time
  2983                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2984                              <1> 	;
  2985                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2986                              <1> 	;
  2987 00002E60 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2988 00002E65 86E9                <1>         xchg 	ch,cl
  2989 00002E67 66890D[44620000]    <1>         mov 	[hour], cx
  2990 00002E6E 86F2                <1>         xchg 	dh,dl
  2991 00002E70 668915[46620000]    <1>         mov 	[second], dx
  2992                              <1> 	;
  2993 00002E77 E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2994 00002E7C 86E9                <1>         xchg 	ch,cl
  2995 00002E7E 66890D[40620000]    <1>         mov 	[year], cx
  2996 00002E85 86F2                <1>         xchg 	dh,dl
  2997 00002E87 668915[42620000]    <1>         mov 	[month], dx
  2998                              <1> 	;
  2999 00002E8E 66B93030            <1> 	mov 	cx, 3030h
  3000                              <1> 	;
  3001 00002E92 A0[44620000]        <1> 	mov 	al, [hour] ; Hour
  3002                              <1>         	; AL <= BCD number)
  3003 00002E97 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3004                              <1> 					; AH = AL / 10h
  3005                              <1> 					; AL = AL MOD 10h
  3006 00002E99 D50A                <1>         aad 	; AX= AH*10+AL
  3007 00002E9B A2[44620000]        <1> 	mov 	[hour], al
  3008 00002EA0 A0[45620000]        <1> 	mov 	al, [hour+1] ; Minute
  3009                              <1>         	; AL <= BCD number)
  3010 00002EA5 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3011                              <1> 					; AH = AL / 10h
  3012                              <1> 					; AL = AL MOD 10h
  3013 00002EA7 D50A                <1>         aad 	; AX= AH*10+AL
  3014 00002EA9 A2[45620000]        <1> 	mov 	[minute], al
  3015 00002EAE A0[46620000]        <1> 	mov 	al, [second] ; Second
  3016                              <1>         	; AL <= BCD number)
  3017 00002EB3 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3018                              <1> 					; AH = AL / 10h
  3019                              <1> 					; AL = AL MOD 10h
  3020 00002EB5 D50A                <1>         aad 	; AX= AH*10+AL
  3021 00002EB7 A2[46620000]        <1> 	mov 	[second], al
  3022 00002EBC 66A1[40620000]      <1> 	mov 	ax, [year] ; Year (century)
  3023                              <1>  	;push 	ax
  3024                              <1> 	; 08/01/2022
  3025 00002EC2 50                  <1> 	push	eax
  3026                              <1> 	   	; AL <= BCD number)
  3027 00002EC3 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3028                              <1> 					; AH = AL / 10h
  3029                              <1> 					; AL = AL MOD 10h
  3030 00002EC5 D50A                <1>         aad 	; AX= AH*10+AL
  3031 00002EC7 B464                <1> 	mov 	ah, 100
  3032 00002EC9 F6E4                <1> 	mul 	ah
  3033 00002ECB 66A3[40620000]      <1> 	mov 	[year], ax
  3034                              <1> 	;pop	ax
  3035                              <1> 	; 08/01/2022
  3036 00002ED1 58                  <1> 	pop	eax
  3037 00002ED2 88E0                <1> 	mov	al, ah
  3038                              <1>         	; AL <= BCD number)
  3039 00002ED4 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3040                              <1> 					; AH = AL / 10h
  3041                              <1> 					; AL = AL MOD 10h
  3042 00002ED6 D50A                <1>         aad 	; AX= AH*10+AL
  3043 00002ED8 660105[40620000]    <1> 	add 	[year], ax
  3044 00002EDF A0[42620000]        <1> 	mov 	al, [month] ; Month
  3045                              <1>            	; AL <= BCD number)
  3046 00002EE4 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3047                              <1> 					; AH = AL / 10h
  3048                              <1> 					; AL = AL MOD 10h
  3049 00002EE6 D50A                <1>         aad 	; AX= AH*10+AL
  3050 00002EE8 A2[42620000]        <1> 	mov 	[month], al	
  3051 00002EED A0[43620000]        <1>         mov     al, [month+1]      	; Day
  3052                              <1>            	; AL <= BCD number)
  3053 00002EF2 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3054                              <1> 					; AH = AL / 10h
  3055                              <1> 					; AL = AL MOD 10h
  3056 00002EF4 D50A                <1>         aad 	; AX= AH*10+AL
  3057 00002EF6 A2[43620000]        <1>         mov     [day], al
  3058                              <1> 	
  3059                              <1> convert_to_epoch:
  3060                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3061                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3062                              <1> 	;
  3063                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3064                              <1> 	;
  3065                              <1> 	; Derived from DALLAS Semiconductor
  3066                              <1> 	; Application Note 31 (DS1602/DS1603)
  3067                              <1> 	; 6 May 1998
  3068 00002EFB 29C0                <1> 	sub 	eax, eax
  3069 00002EFD 66A1[40620000]      <1> 	mov 	ax, [year]
  3070 00002F03 662DB207            <1> 	sub 	ax, 1970
  3071 00002F07 BA6D010000          <1> 	mov 	edx, 365
  3072 00002F0C F7E2                <1> 	mul 	edx
  3073 00002F0E 31DB                <1> 	xor 	ebx, ebx
  3074 00002F10 8A1D[42620000]      <1> 	mov 	bl, [month]
  3075 00002F16 FECB                <1> 	dec 	bl
  3076 00002F18 D0E3                <1> 	shl 	bl, 1
  3077                              <1> 	;sub	edx, edx
  3078 00002F1A 668B93[48620000]    <1> 	mov 	dx, [EBX+DMonth]
  3079 00002F21 8A1D[43620000]      <1>         mov     bl, [day]
  3080 00002F27 FECB                <1> 	dec 	bl
  3081 00002F29 01D0                <1> 	add 	eax, edx
  3082 00002F2B 01D8                <1> 	add 	eax, ebx
  3083                              <1> 			; EAX = days since 1/1/1970
  3084 00002F2D 668B15[40620000]    <1> 	mov 	dx, [year]
  3085 00002F34 6681EAB107          <1> 	sub 	dx, 1969
  3086 00002F39 66D1EA              <1> 	shr 	dx, 1
  3087 00002F3C 66D1EA              <1> 	shr 	dx, 1		
  3088                              <1> 		; (year-1969)/4
  3089 00002F3F 01D0                <1> 	add 	eax, edx
  3090                              <1> 			; + leap days since 1/1/1970
  3091 00002F41 803D[42620000]02    <1> 	cmp 	byte [month], 2	; if past february
  3092 00002F48 7610                <1> 	jna 	short cte1
  3093 00002F4A 668B15[40620000]    <1> 	mov 	dx, [year]
  3094 00002F51 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3095 00002F55 7503                <1> 	jnz 	short cte1		
  3096                              <1> 			; and if leap year
  3097 00002F57 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3098                              <1> cte1: 			; compute seconds since 1/1/1970
  3099 00002F5A BA18000000          <1> 	mov 	edx, 24
  3100 00002F5F F7E2                <1> 	mul	edx
  3101 00002F61 8A15[44620000]      <1> 	mov 	dl, [hour]
  3102 00002F67 01D0                <1> 	add 	eax, edx
  3103                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3104                              <1> 	;mov	ebx, 60
  3105 00002F69 B33C                <1> 	mov	bl, 60
  3106 00002F6B F7E3                <1> 	mul	ebx
  3107 00002F6D 8A15[45620000]      <1> 	mov 	dl, [minute]
  3108 00002F73 01D0                <1> 	add 	eax, edx
  3109                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3110                              <1> 	;mov 	ebx, 60
  3111 00002F75 F7E3                <1> 	mul	ebx
  3112 00002F77 8A15[46620000]      <1> 	mov 	dl, [second]
  3113 00002F7D 01D0                <1> 	add 	eax, edx
  3114                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3115 00002F7F C3                  <1> 	retn
  3116                              <1> 
  3117                              <1> get_rtc_time:
  3118                              <1> 	; 15/03/2015
  3119                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3120                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3121                              <1> 	; INT 1Ah
  3122                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3123                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3124                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3125                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3126                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3127                              <1> 	;								
  3128                              <1> RTC_20: 				; GET RTC TIME
  3129 00002F80 FA                  <1> 	cli
  3130 00002F81 E8B9DBFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3131 00002F86 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3132                              <1> 
  3133 00002F88 B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3134 00002F8A E89ADBFFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3135 00002F8F 88C6                <1> 	MOV	DH, AL			; SAVE
  3136 00002F91 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3137 00002F93 E891DBFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3138 00002F98 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3139 00002F9A 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3140 00002F9C B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3141 00002F9E E886DBFFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3142 00002FA3 88C1                <1> 	MOV	CL, AL			; SAVE
  3143 00002FA5 B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3144 00002FA7 E87DDBFFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3145 00002FAC 88C5                <1> 	MOV	CH, AL			; SAVE
  3146 00002FAE F8                  <1> 	CLC				; SET CY= 0
  3147                              <1> RTC_29:
  3148 00002FAF FB                  <1> 	sti
  3149 00002FB0 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3150                              <1> 
  3151                              <1> get_rtc_date:
  3152                              <1> 	; 15/03/2015
  3153                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3154                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3155                              <1> 	; INT 1Ah
  3156                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3157                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3158                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3159                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3160                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3161                              <1> 	;
  3162                              <1> RTC_40: 				; GET RTC DATE
  3163 00002FB1 FA                  <1> 	cli
  3164 00002FB2 E888DBFFFF          <1> 	CALL	UPD_IPR			; CHECK FOR UPDATE IN PROCESS
  3165 00002FB7 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3166                              <1> 
  3167 00002FB9 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3168 00002FBB E869DBFFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3169 00002FC0 88C2                <1> 	MOV	DL, AL			; SAVE
  3170 00002FC2 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3171 00002FC4 E860DBFFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3172 00002FC9 88C6                <1> 	MOV	DH, AL			; SAVE
  3173 00002FCB B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3174 00002FCD E857DBFFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3175 00002FD2 88C1                <1> 	MOV	CL, AL			; SAVE
  3176 00002FD4 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3177 00002FD6 E84EDBFFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3178 00002FDB 88C5                <1> 	MOV	CH, AL			; SAVE
  3179 00002FDD F8                  <1> 	CLC				; SET CY=0
  3180                              <1> RTC_49:
  3181 00002FDE FB                  <1> 	sti
  3182 00002FDF C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3183                              <1> 
  3184                              <1> set_date_time:
  3185                              <1> convert_from_epoch:
  3186                              <1> 	; 02/06/2022
  3187                              <1> 	; 01/06/2022 (BugFix)
  3188                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3189                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3190                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3191                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3192                              <1> 	;
  3193                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3194                              <1> 	;
  3195                              <1> 	; Derived from DALLAS Semiconductor
  3196                              <1> 	; Application Note 31 (DS1602/DS1603)
  3197                              <1> 	; 6 May 1998
  3198                              <1> 	;
  3199                              <1> 	; INPUT:
  3200                              <1> 	; EAX = Unix (Epoch) Time
  3201                              <1> 	;
  3202 00002FE0 31D2                <1> 	xor 	edx, edx
  3203                              <1> 	; 02/06/2022
  3204 00002FE2 31C9                <1> 	xor	ecx, ecx
  3205 00002FE4 31DB                <1> 	xor	ebx, ebx
  3206                              <1> 	;mov 	ecx, 60
  3207 00002FE6 B13C                <1> 	mov	cl, 60
  3208 00002FE8 F7F1                <1> 	div	ecx
  3209                              <1> 	;mov 	[imin], eax  ; whole minutes
  3210                              <1> 			     ; since 1/1/1970
  3211                              <1> 	;mov 	[second], dx ; leftover seconds
  3212 00002FEA 8815[46620000]      <1> 	mov	[second], dl ; 02/06/2022
  3213 00002FF0 29D2                <1> 	sub 	edx, edx
  3214 00002FF2 F7F1                <1> 	div	ecx
  3215                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3216                              <1> 	;		     ; since 1/1/1970
  3217                              <1> 	;mov 	[minute], dx ; leftover minutes
  3218 00002FF4 8815[45620000]      <1> 	mov	[minute], dl ; 02/06/2022
  3219 00002FFA 31D2                <1> 	xor	edx, edx
  3220                              <1> 	;mov 	cx, 24
  3221 00002FFC B118                <1> 	mov 	cl, 24
  3222 00002FFE F7F1                <1> 	div	ecx
  3223                              <1> 	;mov 	[iday], ax   ; whole days
  3224                              <1> 			     ; since 1/1/1970
  3225                              <1> 	;mov 	[hour], dx   ; leftover hours
  3226 00003000 8815[44620000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3227                              <1> 
  3228 00003006 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3229                              <1> 			     ; 1/1/1968 	
  3230                              <1> 	;mov 	[iday], ax
  3231 0000300B 50                  <1> 	push 	eax
  3232 0000300C 29D2                <1> 	sub	edx, edx
  3233 0000300E B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3234 00003013 F7F1                <1> 	div	ecx
  3235 00003015 59                  <1> 	pop 	ecx
  3236                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3237                              <1> 	;push	dx
  3238                              <1> 	; 01/06/2022
  3239 00003016 52                  <1> 	push 	edx
  3240                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3241 00003017 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3242 0000301B F5                  <1> 	cmc		     ; add this quadyr's leap day
  3243 0000301C 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3244                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3245                              <1> 	;mov 	cx, [iday]
  3246 0000301F 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3247 00003020 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3248 00003022 B96D010000          <1> 	mov 	ecx, 365
  3249 00003027 31D2                <1> 	xor	edx, edx
  3250                              <1> 	; EAX = iday-lday, EDX = 0
  3251 00003029 F7F1                <1> 	div	ecx
  3252                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3253                              <1> 	;jday = iday - (iyrs*365) - lday
  3254                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3255                              <1> 	;add	eax, 1968
  3256 0000302B 6605B007            <1> 	add 	ax, 1968     ; compute year
  3257 0000302F 66A3[40620000]      <1> 	mov 	[year], ax
  3258                              <1> 	;mov 	cx, dx
  3259                              <1> 	; 02/06/2022
  3260 00003035 89D1                <1> 	mov	ecx, edx
  3261                              <1> 	;mov 	dx, [qday]
  3262                              <1> 	;pop	dx
  3263                              <1> 	; 01/06/2022
  3264 00003037 5A                  <1> 	pop 	edx
  3265 00003038 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3266 0000303D 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3267 0000303F 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3268 00003043 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3269 00003044 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3270                              <1> cfe1:			
  3271                              <1> 	;mov 	[jday], cx
  3272                              <1> 	;mov 	bx, 12       ; estimate month
  3273                              <1> 	;sub	ebx, ebx
  3274                              <1> 	; 02/06/2022
  3275 00003048 B30C                <1> 	mov	bl, 12
  3276 0000304A 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3277 0000304E 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3278                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3279                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3280                              <1> 	; 02/06/2022
  3281 00003052 39D1                <1> 	cmp	ecx, edx 	 		
  3282 00003054 7319                <1> 	jnb 	short cfe3
  3283                              <1> 	;dec 	bx           ; month = month - 1
  3284 00003056 FECB                <1> 	dec	bl			
  3285                              <1> 	;shl 	bx, 1
  3286 00003058 D0E3                <1> 	shl	bl, 1
  3287 0000305A 668B93[48620000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3288                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3289                              <1> 	; 02/06/2022
  3290 00003061 D0EB                <1> 	shr	bl, 1
  3291 00003063 80FB01              <1> 	cmp	bl, 1
  3292                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3293 00003066 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3294 00003068 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3295 0000306A 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3296                              <1> 	;inc 	dx           ; mday = mday + 1
  3297 0000306C 42                  <1> 	inc	edx
  3298 0000306D EBE3                <1> 	jmp 	short cfe2
  3299                              <1> cfe3:
  3300                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3301                              <1> 	; 02/06/2022
  3302 0000306F FEC3                <1> 	inc	bl
  3303                              <1> 	;mov 	[month], bx
  3304 00003071 881D[42620000]      <1> 	mov	[month], bl
  3305                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1	
  3306 00003077 29D1                <1> 	sub	ecx, edx
  3307                              <1> 	;inc 	cx 			  
  3308 00003079 FEC1                <1> 	inc	cl
  3309                              <1> 	;mov 	[day], cx
  3310 0000307B 880D[43620000]      <1> 	mov	[day], cl    ; 02/06/2022
  3311                              <1> 	
  3312                              <1> 	; eax, ebx, ecx, edx is changed at return
  3313                              <1> 	; output ->
  3314                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3315                              <1> 
  3316                              <1> 	; 01/06/2022 (BugFix)	
  3317                              <1> _set_date:
  3318 00003081 66A1[40620000]      <1> 	mov	ax, [year]
  3319 00003087 B520                <1> 	mov	ch, 20h ; century (bcd)
  3320 00003089 662DD007            <1> 	sub	ax, 2000
  3321 0000308D 7306                <1> 	jnc	short set_date
  3322 0000308F B519                <1> 	mov	ch, 19h ; century (bcd) 
  3323 00003091 6683C064            <1> 	add	ax, 100	
  3324                              <1> 	; 01/06/2022
  3325                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3326                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3327                              <1> set_date:
  3328                              <1>         ;mov	al, [year+1]
  3329                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3330                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3331                              <1> 	;		     ; AL = AH * 10h + AL
  3332                              <1> 	;mov 	ch, al ; century (BCD)
  3333                              <1> 	;mov 	al, [year]
  3334                              <1> 	; al = year (0-99) ; 01/06/2022
  3335 00003095 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3336 00003097 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3337                              <1> 			     ; AL = AH * 10h + AL
  3338 00003099 88C1                <1> 	mov 	cl, al ; year (BCD)
  3339 0000309B A0[42620000]        <1>         mov 	al, [month]
  3340 000030A0 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3341 000030A2 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3342                              <1> 			     ; AL = AH * 10h + AL
  3343 000030A4 88C6                <1> 	mov 	dh, al ; month (BCD)
  3344 000030A6 A0[43620000]        <1> 	mov 	al, [day]
  3345 000030AB D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3346 000030AD D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3347                              <1> 			     ; AL = AH * 10h + AL
  3348                              <1> 	; 01/06/2022 (BugFix)
  3349 000030AF 88C2                <1> 	mov 	dl, al ; day (BCD)
  3350                              <1> 
  3351                              <1> 	; Set real-time clock date
  3352 000030B1 E879000000          <1> 	call	set_rtc_date
  3353                              <1> set_time:
  3354                              <1>         ; Read real-time clock time 
  3355                              <1> 	; (get day light saving time bit status)
  3356 000030B6 FA                  <1>  	cli
  3357 000030B7 E883DAFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3358                              <1> 	; cf = 1 -> al = 0
  3359 000030BC 7207                <1>         jc      short stime1
  3360 000030BE B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3361 000030C0 E864DAFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3362                              <1> stime1:
  3363 000030C5 FB                  <1> 	sti
  3364 000030C6 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3365 000030C8 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3366                              <1> 	; DL = 1 or 0 (day light saving time)
  3367                              <1> 	;	
  3368 000030CA A0[44620000]        <1> 	mov 	al, [hour]
  3369 000030CF D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3370 000030D1 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3371                              <1> 			     ; AL = AH * 10h + AL
  3372 000030D3 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3373 000030D5 A0[45620000]        <1>         mov     al, [minute]
  3374 000030DA D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3375 000030DC D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3376                              <1> 			     ; AL = AH * 10h + AL
  3377 000030DE 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3378 000030E0 A0[46620000]        <1>         mov     al, [second]
  3379 000030E5 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3380 000030E7 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3381                              <1> 			     ; AL = AH * 10h + AL
  3382 000030E9 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3383                              <1> 
  3384                              <1> 	; Set real-time clock time
  3385                              <1>  	; call	set_rtc_time
  3386                              <1> set_rtc_time:
  3387                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3388                              <1> 	; 15/03/2015
  3389                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3390                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3391                              <1> 	; INT 1Ah
  3392                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3393                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3394                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3395                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3396                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3397                              <1> 	;								:
  3398                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3399                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3400                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3401                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3402                              <1> 	;
  3403                              <1> RTC_30: 				; SET RTC TIME
  3404 000030EB FA                  <1> 	cli
  3405 000030EC E84EDAFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3406 000030F1 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3407 000030F3 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3408                              <1> RTC_35:
  3409 000030F8 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3410 000030FA B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3411 000030FC E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3412 00003101 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3413 00003103 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3414 00003105 E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3415 0000310A 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3416 0000310C B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3417 0000310E E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3418                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3419 00003113 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3420 00003117 E80DDAFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3421 0000311C 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3422 0000311E 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3423 00003120 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3424 00003123 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3425 00003125 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3426 00003127 E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3427 0000312C F8                  <1> 	CLC				; SET CY= 0
  3428 0000312D FB                  <1> 	sti
  3429 0000312E C3                  <1> 	RETn				; RETURN WITH CY= 0
  3430                              <1> 
  3431                              <1> set_rtc_date:
  3432                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3433                              <1> 	; 15/03/2015
  3434                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3435                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3436                              <1> 	; INT 1Ah
  3437                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3438                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3439                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3440                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3441                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3442                              <1> 	;
  3443                              <1> RTC_50: 				; SET RTC DATE
  3444 0000312F FA                  <1> 	cli
  3445 00003130 E80ADAFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3446 00003135 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3447 00003137 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3448                              <1> RTC_55:
  3449 0000313C 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3450 00003140 E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3451 00003145 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3452 00003147 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3453 00003149 E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3454 0000314E 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3455 00003150 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3456 00003152 E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3457 00003157 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3458 00003159 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3459 0000315B E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3460 00003160 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3461 00003162 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3462 00003164 E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3463                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3464 00003169 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3465 0000316D E8B7D9FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3466 00003172 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3467 00003174 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3468 00003176 E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3469 0000317B F8                  <1> 	CLC				; SET CY= 0
  3470 0000317C FB                  <1> 	sti
  3471 0000317D C3                  <1> 	RETn				; RETURN CY=0
  3472                              <1> 
  3473                              <1> 	; 15/03/2015
  3474                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3475 0000317E B426                <1> 	mov	ah, 26h
  3476 00003180 B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3477 00003182 E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3478 00003187 B482                <1> 	mov	ah, 82h
  3479 00003189 B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3480 0000318B E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3481 00003190 B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3482 00003192 E892D9FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3483 00003197 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3484                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3485                              <1> 	;RETn
  3486                              <1> 	; 12/01/2022
  3487 00003199 E98BD9FFFF          <1> 	jmp	CMOS_READ
  3488                              <1> 
  3489                              <1> 	; 15/03/2015
  3490                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3491                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3492 0000319E 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3493                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3494 0000319F D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3495 000031A1 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3496 000031A2 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3497 000031A4 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3498 000031A5 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3499 000031A7 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3500 000031A9 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3501 000031AB B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3502 000031AD D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3503 000031AF E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3504 000031B1 90                  <1> 	nop			; I/O DELAY
  3505 000031B2 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3506                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3507 000031B4 9D                  <1> 	popf	
  3508 000031B5 C3                  <1> 	RETn
  3509                              <1> 
  3510                              <1> bf_init:
  3511                              <1> 	; 14/08/2015
  3512                              <1> 	; 02/07/2015
  3513                              <1> 	; 01/07/2015
  3514                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3515                              <1> 	; Buffer (pointer) initialization !
  3516                              <1> 	; 
  3517                              <1> 	; 17/07/2013 - 24/07/2013
  3518                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3519                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3520                              <1> 	;
  3521 000031B6 BF[58680000]        <1> 	mov	edi, bufp 
  3522 000031BB B8[50750000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3523 000031C0 29D2                <1> 	sub	edx, edx
  3524 000031C2 FECA                <1> 	dec	dl
  3525 000031C4 31C9                <1> 	xor	ecx, ecx
  3526 000031C6 49                  <1> 	dec	ecx
  3527                              <1> bi0:
  3528 000031C7 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3529 000031CC AB                  <1> 	stosd
  3530 000031CD 89C6                <1> 	mov	esi, eax
  3531 000031CF 8916                <1> 	mov	[esi], edx ; 000000FFh
  3532                              <1> 			   ; Not a valid device sign
  3533 000031D1 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3534                              <1> 		      ; Not a valid block number sign 	 	
  3535 000031D4 3D[20690000]        <1> 	cmp	eax, buffer
  3536 000031D9 77EC                <1> 	ja	short bi0
  3537 000031DB B8[50750000]        <1> 	mov	eax, sb0
  3538 000031E0 AB                  <1> 	stosd
  3539 000031E1 B8[58770000]        <1> 	mov	eax, sb1
  3540 000031E6 AB                  <1> 	stosd
  3541 000031E7 89C6                <1> 	mov	esi, eax ; offset sb1
  3542 000031E9 8916                <1> 	mov	[esi], edx ; 000000FFh
  3543                              <1> 			   ; Not a valid device sign
  3544 000031EB 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3545                              <1> 		      ; Not a valid block number sign 	 
  3546                              <1> 	; 14/08/2015
  3547                              <1> 	;call 	rdev_init
  3548                              <1> 	;retn
  3549                              <1> 
  3550                              <1> rdev_init: ; root device, super block buffer initialization
  3551                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3552                              <1> 	; 14/08/2015
  3553                              <1> 	; Retro UNIX 386 v1 feature only !
  3554                              <1> 	;
  3555                              <1> 	; NOTE: Disk partitions (file systems), logical
  3556                              <1> 	; drive initialization, partition's start sector etc.
  3557                              <1> 	; will be coded here, later in 'ldrv_init'	
  3558                              <1> 
  3559 000031EE 0FB605[CA5F0000]    <1> 	movzx	eax, byte [boot_drv]
  3560                              <1> rdi_0:
  3561 000031F5 3C80                <1> 	cmp	al, 80h
  3562 000031F7 7202                <1> 	jb	short rdi_1
  3563 000031F9 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3564                              <1> rdi_1:
  3565 000031FB A2[7C680000]        <1> 	mov	[rdev], al
  3566 00003200 BB[50750000]        <1>         mov	ebx, sb0 ; super block buffer
  3567 00003205 8903                <1> 	mov 	[ebx], eax
  3568 00003207 B001                <1> 	mov	al, 1 ; eax = 1
  3569 00003209 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3570                              <1> 	;call 	diskio
  3571                              <1> 	;retn
  3572                              <1> 	; 24/12/2021
  3573 0000320C E9C8250000          <1> 	jmp	diskio
  3574                              <1> 
  3575                              <1> ; 23/10/2015
  3576                              <1> com1_irq4:
  3577 00003211 [19320000]          <1> 	dd	dummy_retn
  3578                              <1> com2_irq3:
  3579 00003215 [19320000]          <1> 	dd	dummy_retn
  3580                              <1> 
  3581                              <1> dummy_retn:
  3582 00003219 C3                  <1> 	retn
  2105                                  %include 'u1.s'        ; 10/05/2015
  2106                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS1.INC
  2107                              <1> ; Last Modification: 27/02/2022
  2108                              <1> ; ----------------------------------------------------------------------------
  2109                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2110                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2111                              <1> ;
  2112                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2113                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2114                              <1> ; <Bell Laboratories (17/3/1972)>
  2115                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2116                              <1> ;
  2117                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2118                              <1> ;
  2119                              <1> ; ****************************************************************************
  2120                              <1> 
  2121                              <1> unkni: ; / used for all system calls
  2122                              <1> sysent: ; < enter to system call >
  2123                              <1> 	; 08/01/2022
  2124                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2125                              <1> 	; 19/10/2015
  2126                              <1> 	; 21/09/2015
  2127                              <1> 	; 01/07/2015
  2128                              <1> 	; 19/05/2015
  2129                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2130                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2131                              <1> 	;
  2132                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2133                              <1> 	; The trap type is determined and an indirect jump is made to 
  2134                              <1> 	; the appropriate system call handler. If there is a trap inside
  2135                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2136                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2137                              <1> 	; instructor is decoded to get the the system code part (see
  2138                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2139                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2140                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2141                              <1> 	; is called. If the call is legitimate control passes to the
  2142                              <1> 	; appropriate system routine.
  2143                              <1> 	;
  2144                              <1> 	; Calling sequence:
  2145                              <1> 	;	Through a trap caused by any sys call outside the system.
  2146                              <1> 	; Arguments:
  2147                              <1> 	;	Arguments of particular system call.	
  2148                              <1> 	; ...............................................................
  2149                              <1> 	;	
  2150                              <1> 	; Retro UNIX 8086 v1 modification: 
  2151                              <1> 	;       System call number is in EAX register.
  2152                              <1> 	;
  2153                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2154                              <1> 	;	registers depending of function details.
  2155                              <1>   	;
  2156                              <1> 	; 16/04/2015
  2157 0000321A 368925[90680000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2158                              <1> 	; save user registers
  2159 00003221 1E                  <1> 	push	ds
  2160 00003222 06                  <1> 	push	es
  2161 00003223 0FA0                <1> 	push	fs
  2162 00003225 0FA8                <1> 	push	gs
  2163 00003227 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2164                              <1> 	;
  2165                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2166                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2167                              <1> 	;	for saving/restoring user registers.)
  2168                              <1> 	;
  2169 00003228 50                  <1> 	push	eax ; 01/07/2015
  2170 00003229 66B81000            <1> 	mov     ax, KDATA
  2171 0000322D 8ED8                <1>         mov     ds, ax
  2172 0000322F 8EC0                <1>         mov     es, ax
  2173 00003231 8EE0                <1>         mov     fs, ax
  2174 00003233 8EE8                <1>         mov     gs, ax
  2175 00003235 A1[D8640000]        <1> 	mov	eax, [k_page_dir]
  2176 0000323A 0F22D8              <1> 	mov	cr3, eax
  2177 0000323D 58                  <1> 	pop	eax ; 01/07/2015
  2178                              <1> 	; 19/10/2015
  2179 0000323E FC                  <1> 	cld
  2180                              <1> 	;
  2181 0000323F FE05[8D680000]      <1> 	inc	byte [sysflg]
  2182                              <1> 		; incb sysflg / indicate a system routine is in progress
  2183 00003245 FB                  <1>         sti 	; 18/01/2014
  2184                              <1> 	;jnz	panic ; 24/05/2013
  2185                              <1> 	; 24/12/2021
  2186 00003246 7405                <1> 	jz	short _1
  2187 00003248 E984F9FFFF          <1> 	jmp	panic
  2188                              <1> 		; beq 1f
  2189                              <1> 		; jmp panic ; / called if trap inside system
  2190                              <1> ;1:
  2191                              <1> _1:	; 24/12/2021
  2192                              <1> 	; 16/04/2015
  2193 0000324D A3[98680000]        <1> 	mov	[u.r0], eax
  2194 00003252 8925[94680000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2195                              <1> 	;
  2196                              <1> 		; mov $s.syst+2,clockp
  2197                              <1> 		; mov r0,-(sp) / save user registers 
  2198                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2199                              <1> 			   ; / in u.r0
  2200                              <1> 		; mov r1,-(sp)
  2201                              <1> 		; mov r2,-(sp)
  2202                              <1> 		; mov r3,-(sp)
  2203                              <1> 		; mov r4,-(sp)
  2204                              <1> 		; mov r5,-(sp)
  2205                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2206                              <1> 		             ; / arithmetic unit
  2207                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2208                              <1> 		             ; / extended arithmetic unit
  2209                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2210                              <1> 		             ; / arithmetic unit
  2211                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2212                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2213                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2214                              <1> 		; sub $sys,r0 / get xxx code
  2215 00003258 C1E002              <1> 	shl	eax, 2
  2216                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2217 0000325B 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2218                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2219                              <1> 	;jnb	short badsys
  2220                              <1> 		; bhis badsys / yes, bad system call
  2221                              <1> 	; 08/01/2022
  2222 00003260 7205                <1> 	jb	short _2
  2223 00003262 E95D010000          <1> 	jmp	badsys
  2224                              <1> _2:
  2225                              <1> 	; 08/01/2022
  2226                              <1> 	;cmc
  2227                              <1> 	;pushf	
  2228                              <1> 	;push	eax
  2229 00003267 8B2D[90680000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2230                              <1> 	;mov	al, 0FEh ; 11111110b
  2231                              <1> 	;;adc	al, 0 ; al = al + cf
  2232                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2233 0000326D 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2234                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2235                              <1> 				 ; / and clear carry bit
  2236                              <1> 	;pop	ebp ; eax
  2237 00003271 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2238                              <1> 	;popf
  2239                              <1>         ;;jc	badsys
  2240                              <1> 	; 24/12/2021
  2241                              <1> 	;jnc	short _3  ; 08/01/2022
  2242                              <1> 	;jmp	badsys
  2243                              <1> ;_3:
  2244 00003273 A1[98680000]        <1> 	mov	eax, [u.r0]
  2245                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2246 00003278 FFA5[7E320000]      <1> 	jmp	dword [ebp+syscalls]
  2247                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2248                              <1> 		            ; / to proper system routine.
  2249                              <1> syscalls: ; 1:
  2250                              <1> 	; 21/09/2015
  2251                              <1> 	; 01/07/2015
  2252                              <1> 	; 16/04/2015 (32 bit address modification) 
  2253 0000327E [8E330000]          <1> 	dd sysrele	; / 0
  2254 00003282 [36340000]          <1> 	dd sysexit 	; / 1
  2255 00003286 [61350000]          <1> 	dd sysfork 	; / 2
  2256 0000328A [67360000]          <1> 	dd sysread 	; / 3
  2257 0000328E [7A360000]          <1> 	dd syswrite 	; / 4
  2258 00003292 [E3360000]          <1> 	dd sysopen 	; / 5
  2259 00003296 [0E380000]          <1> 	dd sysclose 	; / 6
  2260 0000329A [DC340000]          <1> 	dd syswait 	; / 7
  2261 0000329E [8B370000]          <1> 	dd syscreat 	; / 8
  2262 000032A2 [C73B0000]          <1> 	dd syslink 	; / 9
  2263 000032A6 [833C0000]          <1> 	dd sysunlink 	; / 10
  2264 000032AA [4D3D0000]          <1> 	dd sysexec 	; / 11
  2265 000032AE [D0430000]          <1> 	dd syschdir 	; / 12
  2266 000032B2 [B3440000]          <1> 	dd systime 	; / 13
  2267 000032B6 [C7370000]          <1> 	dd sysmkdir 	; / 14
  2268 000032BA [20440000]          <1> 	dd syschmod 	; / 15
  2269 000032BE [83440000]          <1> 	dd syschown 	; / 16
  2270 000032C2 [E6440000]          <1> 	dd sysbreak 	; / 17
  2271 000032C6 [0D410000]          <1> 	dd sysstat 	; / 18
  2272 000032CA [B6450000]          <1> 	dd sysseek 	; / 19
  2273 000032CE [C8450000]          <1> 	dd systell 	; / 20
  2274 000032D2 [FC500000]          <1> 	dd sysmount 	; / 21
  2275 000032D6 [E7510000]          <1> 	dd sysumount 	; / 22
  2276 000032DA [44460000]          <1> 	dd syssetuid 	; / 23
  2277 000032DE [75460000]          <1> 	dd sysgetuid 	; / 24
  2278 000032E2 [C2440000]          <1> 	dd sysstime 	; / 25
  2279 000032E6 [38460000]          <1> 	dd sysquit 	; / 26
  2280 000032EA [2C460000]          <1> 	dd sysintr 	; / 27
  2281 000032EE [EA400000]          <1> 	dd sysfstat 	; / 28
  2282 000032F2 [2B380000]          <1> 	dd sysemt 	; / 29
  2283 000032F6 [77380000]          <1> 	dd sysmdate 	; / 30
  2284 000032FA [D1380000]          <1> 	dd sysstty 	; / 31
  2285 000032FE [BA3A0000]          <1> 	dd sysgtty 	; / 32
  2286 00003302 [72380000]          <1> 	dd sysilgins 	; / 33
  2287 00003306 [915A0000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2288                              <1> 			     ; 11/06/2014
  2289 0000330A [A85A0000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2290                              <1> 			     ; 01/07/2015
  2291 0000330E [805B0000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2292                              <1> 			     ; 21/09/2015 - get last error number
  2293                              <1> end_of_syscalls:
  2294                              <1> 
  2295                              <1> error:
  2296                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2297                              <1> 	; 17/09/2015
  2298                              <1> 	; 03/09/2015
  2299                              <1> 	; 01/09/2015
  2300                              <1> 	; 09/06/2015
  2301                              <1> 	; 13/05/2015
  2302                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2303                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2304                              <1> 	;
  2305                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2306                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2307                              <1> 	;
  2308                              <1> 	; INPUTS -> none
  2309                              <1> 	; OUTPUTS ->
  2310                              <1> 	;	processor status - carry (c) bit is set (means error)
  2311                              <1> 	;
  2312                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2313                              <1> 	; 	      Because, jumps to error procedure
  2314                              <1> 	;	      disrupts push-pop nesting balance)
  2315                              <1> 	;
  2316 00003312 8B2D[90680000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2317 00003318 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2318                              <1> 				 ; (system call will return with cf = 1)
  2319                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2320                              <1> 		               ; / users stack
  2321                              <1> 	; 17/09/2015
  2322 0000331C 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2323                              <1> 				 ; for saving/restoring user registers	
  2324                              <1> 	;cmp	ebp, [u.usp]
  2325                              <1> 	;je	short err0	
  2326 0000331F 892D[94680000]      <1> 	mov	[u.usp], ebp
  2327                              <1> ;err0:
  2328                              <1> 	; 01/09/2015
  2329 00003325 8B25[94680000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2330                              <1> 				    ; 10/04/2013
  2331                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2332                              <1> 				    ; related procedures will jump to 'error'
  2333                              <1> 				    ; procedure directly without returning to 
  2334                              <1> 				    ; the caller procedure. So, stack pointer
  2335                              <1>                                     ; must be restored here.)
  2336                              <1> 	; 13/05/2015
  2337                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2338                              <1> 	;	'get last error' system call later. 	
  2339                              <1> 
  2340                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2341 0000332B C605[FF680000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2342                              <1> 
  2343                              <1> sysret: ; < return from system call>
  2344                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2345                              <1> 	; 10/09/2015
  2346                              <1> 	; 29/07/2015
  2347                              <1> 	; 25/06/2015
  2348                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2349                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2350                              <1> 	;
  2351                              <1> 	; 'sysret' first checks to see if process is about to be 
  2352                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2353                              <1> 	; If not, following happens:	 
  2354                              <1> 	; 	1) The user's stack pointer is restored.
  2355                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2356                              <1> 	;	   i-node has been modified. If it has, it is written out
  2357                              <1> 	;	   via 'ppoke'.
  2358                              <1> 	;	3) If the super block has been modified, it is written out
  2359                              <1> 	;	   via 'ppoke'.				
  2360                              <1> 	;	4) If the dismountable file system's super block has been
  2361                              <1> 	;	   modified, it is written out to the specified device
  2362                              <1> 	;	   via 'ppoke'.
  2363                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2364                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2365                              <1> 	;	   another user a chance to run.
  2366                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2367                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2368                              <1> 	;
  2369                              <1> 	; Calling sequence:
  2370                              <1> 	;	jump table or 'br sysret'
  2371                              <1> 	; Arguments: 
  2372                              <1> 	;	-	
  2373                              <1> 	; ...............................................................
  2374                              <1> 	;	
  2375                              <1> 	; ((AX=r1 for 'iget' input))
  2376                              <1> 	;	
  2377                              <1> 	;xor	ax, ax ; 04/05/2013
  2378                              <1> 	; 24/12/2021
  2379 00003332 31C0                <1> 	xor	eax, eax
  2380                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2381 00003334 FEC0                <1> 	inc	al ; 04/05/2013
  2382 00003336 3805[E6680000]      <1> 	cmp	[u.bsys], al ; 1
  2383                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2384                              <1> 	;jnb	sysexit ; 04/05/2013
  2385                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2386                              <1> 	; 24/12/2021
  2387 0000333C 720F                <1> 	jb	short _3
  2388 0000333E C705[ED680000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2388 00003346 0000                <1>
  2389 00003348 E9E9000000          <1> 	jmp	sysexit
  2390                              <1> _3:
  2391                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2392                              <1> 		; mov u.sp,sp / no point stack to users stack
  2393 0000334D FEC8                <1> 	dec 	al ; mov ax, 0
  2394                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2395 0000334F E8DB160000          <1> 	call	iget
  2396                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2397                              <1> 		            ; / it is written out
  2398                              <1> 	;xor 	ax, ax ; 0
  2399                              <1> 	; 24/12/2021
  2400 00003354 31C0                <1> 	xor	eax, eax
  2401 00003356 3805[8B680000]      <1> 	cmp	[smod], al ; 0
  2402                              <1> 		; tstb	smod / has the super block been modified
  2403 0000335C 7614                <1> 	jna	short sysret1
  2404                              <1> 		; beq	1f / no, 1f
  2405 0000335E A2[8B680000]        <1> 	mov	[smod], al ; 0
  2406                              <1> 		; clrb smod / yes, clear smod
  2407 00003363 BB[50750000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2408 00003368 66810B0002          <1>    	or	word [ebx], 200h ;;
  2409                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2410                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2411                              <1> 		      	      ; / output
  2412                              <1> 	; AX = 0
  2413 0000336D E84F230000          <1> 	call 	poke ; 07/08/2013
  2414                              <1> 	; call	ppoke
  2415                              <1> 	; AX = 0
  2416                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2417                              <1> sysret1: ;1:
  2418 00003372 3805[8C680000]      <1> 	cmp	[mmod], al ; 0
  2419                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2420                              <1> 		           ; / system
  2421 00003378 7614                <1> 	jna	short sysrel0
  2422                              <1> 		; beq 1f / been modified?  no, 1f
  2423 0000337A A2[8C680000]        <1> 	mov	[mmod], al ; 0	
  2424                              <1> 		; clrb	mmod / yes, clear mmod
  2425                              <1>         ;mov    ax, [mntd]
  2426                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2427 0000337F BB[58770000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2428                              <1>         ;;mov	[ebx], al
  2429                              <1> 	;mov    [sb1], al
  2430                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2431 00003384 66810B0002          <1> 	or	word [ebx], 200h
  2432                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2433                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2434 00003389 E833230000          <1> 	call	poke ; 07/08/2013
  2435                              <1> 	;call	ppoke 
  2436                              <1> 		; jsr r0,ppoke / write it out to its device
  2437                              <1>         ;xor    al, al ; 26/04/2013       
  2438                              <1> ;1:
  2439                              <1> 		; tstb uquant / is the time quantum 0?
  2440                              <1> 		; bne 1f / no, don't swap it out
  2441                              <1> 
  2442                              <1> sysrele: ; < release >
  2443                              <1> 	; 14/10/2015
  2444                              <1> 	; 01/09/2015
  2445                              <1> 	; 24/07/2015
  2446                              <1> 	; 14/05/2015
  2447                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2448                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2449                              <1> 	;
  2450                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2451                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2452                              <1> 	; turns off the system flag. It then checked to see if there is
  2453                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2454                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2455                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2456                              <1> 	; the user, a rti is made.
  2457                              <1> 	;
  2458                              <1> 	; Calling sequence:
  2459                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2460                              <1> 	; Arguments:
  2461                              <1> 	;	-	
  2462                              <1> 	; ...............................................................
  2463                              <1> 	;	
  2464                              <1> 	; 23/02/2014 (swapret)
  2465                              <1> 	; 22/09/2013
  2466                              <1> sysrel0: ;1:
  2467 0000338E 803D[DA680000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2468                              <1> 		; tstb uquant / is the time quantum 0?
  2469 00003395 7705                <1>         ja      short swapret
  2470                              <1> 		; bne 1f / no, don't swap it out
  2471                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2472 00003397 E829130000          <1> 	call	tswap
  2473                              <1> 		; jsr r0,tswap / yes, swap it out
  2474                              <1> ;
  2475                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2476                              <1> swapret: ;1:
  2477                              <1> 	; 10/09/2015
  2478                              <1> 	; 01/09/2015
  2479                              <1> 	; 14/05/2015
  2480                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2481                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2482                              <1> 	; cli
  2483                              <1> 	; 24/07/2015
  2484                              <1> 	;
  2485                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2486                              <1> 	;; mov	esp, [u.usp]
  2487                              <1> 
  2488                              <1> 	; 22/09/2013
  2489 0000339C E8FB140000          <1> 	call	isintr
  2490                              <1> 	; 20/10/2013
  2491 000033A1 7405                <1> 	jz	short sysrel1
  2492 000033A3 E877000000          <1> 	call	intract
  2493                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2494                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2495                              <1> 		               ; / action
  2496                              <1> sysrel1:
  2497 000033A8 FA                  <1> 	cli ; 14/10/2015
  2498 000033A9 FE0D[8D680000]      <1> 	dec	byte [sysflg]
  2499                              <1> 		; decb sysflg / turn system flag off
  2500 000033AF A1[F1680000]        <1> 	mov     eax, [u.pgdir]
  2501 000033B4 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2502                              <1> 			  ; (others are different than kernel page tables) 
  2503                              <1> 	; 10/09/2015
  2504 000033B7 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2505                              <1> 		; mov (sp)+,sc / restore user registers
  2506                              <1> 		; mov (sp)+,mq
  2507                              <1> 		; mov (sp)+,ac
  2508                              <1> 		; mov (sp)+,r5
  2509                              <1> 		; mov (sp)+,r4
  2510                              <1> 		; mov (sp)+,r3
  2511                              <1> 		; mov (sp)+,r2
  2512                              <1> 	;
  2513 000033B8 A1[98680000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2514 000033BD 0FA9                <1> 	pop	gs
  2515 000033BF 0FA1                <1> 	pop	fs
  2516 000033C1 07                  <1> 	pop	es
  2517 000033C2 1F                  <1> 	pop	ds
  2518 000033C3 CF                  <1> 	iretd	
  2519                              <1> 		; rti / no, return from interrupt
  2520                              <1> 
  2521                              <1> badsys:
  2522                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2523                              <1> 	; (Major Modification: 'core' dumping procedure in
  2524                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2525                              <1> 	;	has been changed to print 'Invalid System Call !'
  2526                              <1> 	;	message on the user's console tty.)
  2527                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2528                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2529                              <1> 	; (EAX = Function number)  
  2530                              <1> 	;
  2531 000033C4 FE05[E6680000]      <1> 	inc	byte [u.bsys]
  2532                              <1> 	;
  2533 000033CA 8B1D[90680000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2534 000033D0 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2535 000033D2 E818E3FFFF          <1> 	call	dwordtohex
  2536 000033D7 8915[34620000]      <1> 	mov	[bsys_msg_eip], edx
  2537 000033DD A3[38620000]        <1> 	mov	[bsys_msg_eip+4], eax
  2538 000033E2 A1[98680000]        <1> 	mov	eax, [u.r0]
  2539 000033E7 E803E3FFFF          <1> 	call	dwordtohex
  2540 000033EC 8915[24620000]      <1> 	mov	[bsys_msg_eax], edx
  2541 000033F2 A3[28620000]        <1> 	mov	[bsys_msg_eax+4], eax
  2542                              <1> 	; 24/12/2021
  2543                              <1> 	;xor	eax, eax
  2544                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2545                              <1> 	;mov	ebx, [u.fofp]
  2546                              <1> 	;mov	[ebx], eax
  2547                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2548                              <1> 	;inc	eax
  2549                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2550                              <1> 		; writei
  2551                              <1> 		; INPUTS ->
  2552                              <1> 		;    r1 - inode number
  2553                              <1> 		;    u.count - byte count to be written
  2554                              <1> 		;    u.base - points to user buffer
  2555                              <1> 		;    u.fofp - points to word with current file offset
  2556                              <1> 		; OUTPUTS ->
  2557                              <1> 		;    u.count - cleared
  2558                              <1> 		;    u.nread - accumulates total bytes passed back	
  2559                              <1> 		;
  2560                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2561                              <1> 	;call	writei
  2562                              <1> 	;;mov	eax, 1
  2563                              <1> 	;jmp	sysexit
  2564                              <1> 
  2565                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  2566 000033F7 BE[05620000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2567 000033FC 0FB61D[E7680000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2568 00003403 8A83[F3650000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2569 00003409 C605[07650000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2570 00003410 A2[EC680000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2571 00003415 E84B270000          <1> 	call	print_cmsg
  2572                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2573 0000341A E9F3FEFFFF          <1> 	jmp	error
  2574                              <1> 
  2575                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2576                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2577                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2578                              <1> 		; br 1f / error
  2579                              <1> 		; neg r1 / negate the i-number to open the core image file
  2580                              <1> 		       ; / for writing
  2581                              <1> 		; jsr r0,iopen / open the core image file
  2582                              <1> 		; jsr r0,itrunc / free all associated blocks
  2583                              <1> 		; br 2f
  2584                              <1> ;1:
  2585                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2586                              <1> 		; jsr r0,maknod / make an i-node
  2587                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2588                              <1> ;2:
  2589                              <1> 		; mov $core,u.base / move address core to u.base
  2590                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2591                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2592                              <1> 		; clr u.off / clear user offset
  2593                              <1> 		; jsr r0,writei / write out the core image to the user
  2594                              <1> 		; mov $user,u.base / pt. u.base to user
  2595                              <1> 		; mov $64.,u.count / u.count = 64
  2596                              <1> 		; jsr r0,writei / write out all the user parameters
  2597                              <1> 		; neg r1 / make i-number positive
  2598                              <1> 		; jsr r0,iclose / close the core image file
  2599                              <1> 		; br sysexit /
  2600                              <1> ;3:
  2601                              <1> 		; <core\0\0>
  2602                              <1> 
  2603                              <1> intract: ; / interrupt action
  2604                              <1> 	; 14/10/2015
  2605                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2606                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2607                              <1> 	;
  2608                              <1> 	; Retro UNIX 8086 v1 modification !
  2609                              <1> 	; (Process/task switching and quit routine by using
  2610                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2611                              <1> 	;
  2612                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2613                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2614                              <1> 	;		'intract' will jump to 'sysexit'.
  2615                              <1> 	;	    Intract will return to the caller 
  2616                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2617                              <1> 	; 14/10/2015
  2618 0000341F FB                  <1> 	sti
  2619                              <1> 	; 07/12/2013	
  2620 00003420 66FF05[DE680000]    <1> 	inc 	word [u.quit]
  2621 00003427 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2622 00003429 66FF0D[DE680000]    <1> 	dec	word [u.quit]
  2623                              <1> 	; 16/04/2015
  2624 00003430 C3                  <1> 	retn
  2625                              <1> intrct0:	
  2626 00003431 58                  <1> 	pop	eax ; call intract -> retn
  2627                              <1> 	;
  2628 00003432 31C0                <1> 	xor 	eax, eax
  2629 00003434 FEC0                <1> 	inc	al  ; mov ax, 1
  2630                              <1> ;;;
  2631                              <1> 	; UNIX v1 original 'intract' routine... 
  2632                              <1> 	; / interrupt action
  2633                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2634                              <1> 		; bne 1f / no, 1f
  2635                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2636                              <1> 	; 1: / now in user area
  2637                              <1> 		; mov r1,-(sp) / save r1
  2638                              <1> 		; mov u.ttyp,r1 
  2639                              <1> 			; / pointer to tty buffer in control-to r1
  2640                              <1> 		; cmpb 6(r1),$177
  2641                              <1> 			; / is the interrupt char equal to "del"
  2642                              <1> 		; beq 1f / yes, 1f
  2643                              <1> 		; clrb 6(r1) 
  2644                              <1> 		        ; / no, clear the byte 
  2645                              <1> 			; / (must be a quit character)
  2646                              <1> 		; mov (sp)+,r1 / restore r1
  2647                              <1> 		; clr u.quit / clear quit flag
  2648                              <1> 		; bis $20,2(sp) 
  2649                              <1> 		    	; / set trace for quit (sets t bit of 
  2650                              <1> 			; / ps-trace trap)
  2651                              <1> 		; rti   ;  / return from interrupt
  2652                              <1> 	; 1: / interrupt char = del
  2653                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2654                              <1> 			   ; / in the buffer
  2655                              <1> 		; mov (sp)+,r1 / restore r1
  2656                              <1> 		; cmp u.intr,$core / should control be 
  2657                              <1> 				; / transferred to loc core?
  2658                              <1> 		; blo 1f
  2659                              <1> 		; jmp *u.intr / user to do rti yes, 
  2660                              <1> 				; / transfer to loc core
  2661                              <1> 	; 1:
  2662                              <1> 		; sys 1 / exit
  2663                              <1> 
  2664                              <1> sysexit: ; <terminate process>
  2665                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2666                              <1> 	; 01/09/2015
  2667                              <1> 	; 31/08/2015
  2668                              <1> 	; 14/05/2015
  2669                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2670                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2671                              <1> 	;
  2672                              <1> 	; 'sysexit' terminates a process. First each file that
  2673                              <1> 	; the process has opened is closed by 'flose'. The process
  2674                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2675                              <1> 	; searched to find children of the dying process. If any of
  2676                              <1> 	; children are zombies (died by not waited for), they are
  2677                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2678                              <1> 	; dying process's parent. When the parent is found, it is
  2679                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2680                              <1> 	; one of these, the dying process just dies. If it is waiting
  2681                              <1> 	; for a child process to die, it notified that it doesn't 
  2682                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2683                              <1> 	; (waiting to active). It is awakened and put on runq by
  2684                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2685                              <1> 	; it will never be run again but stays around until a 'wait'
  2686                              <1> 	; is completed by it's parent process. If the parent is not
  2687                              <1> 	; found, process just dies. This means 'swap' is called with
  2688                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2689                              <1> 	; to write out the process and 'rswap' reads the new process
  2690                              <1> 	; over the one that dies..i.e., the dying process is 
  2691                              <1> 	; overwritten and destroyed.	
  2692                              <1>  	;
  2693                              <1> 	; Calling sequence:
  2694                              <1> 	;	sysexit or conditional branch.
  2695                              <1> 	; Arguments:
  2696                              <1> 	;	-	
  2697                              <1> 	; ...............................................................
  2698                              <1> 	;	
  2699                              <1> 	; Retro UNIX 8086 v1 modification: 
  2700                              <1> 	;       System call number (=1) is in EAX register.
  2701                              <1> 	;
  2702                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2703                              <1> 	;       registers depending of function details.
  2704                              <1> 	;
  2705                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2706                              <1> 	;
  2707                              <1> ; / terminate process
  2708                              <1> 	; AX = 1
  2709                              <1> 	;dec 	ax ; 0
  2710                              <1> 	; 24/12/2021
  2711 00003436 48                  <1> 	dec	eax ; 0
  2712                              <1> 	;dec 	ax ; 0
  2713 00003437 66A3[DC680000]      <1> 	mov	[u.intr], ax ; 0
  2714                              <1> 		; clr u.intr / clear interrupt control word
  2715                              <1> 		; clr r1 / clear r1
  2716                              <1> 	; AX = 0
  2717                              <1> sysexit_1: ; 1:
  2718                              <1> 	; AX = File descriptor
  2719                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2720                              <1> 		; / Search the whole list
  2721 0000343D E8690D0000          <1> 	call	fclose
  2722                              <1> 		; jsr r0,fclose / close all files the process opened
  2723                              <1> 	;; ignore error return
  2724                              <1> 		; br .+2 / ignore error return
  2725                              <1> 	;inc	ax
  2726 00003442 FEC0                <1> 	inc	al
  2727                              <1> 		; inc r1 / increment file descriptor
  2728                              <1> 	;cmp	ax, 10
  2729 00003444 3C0A                <1> 	cmp	al, 10
  2730                              <1> 		; cmp r1,$10. / end of u.fp list?
  2731 00003446 72F5                <1> 	jb	short sysexit_1
  2732                              <1> 		; blt 1b / no, go back
  2733 00003448 0FB61D[E7680000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2734                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2735 0000344F 88A3[13660000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2736                              <1> 		; clrb p.stat-1(r1) / free the process
  2737                              <1> 	;shl	bx, 1
  2738 00003455 D0E3                <1> 	shl	bl, 1
  2739                              <1> 		; asl r1 / use r1 for index into the below tables
  2740 00003457 668B8B[B2650000]    <1> 	mov	cx, [ebx+p.pid-2]
  2741                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2742 0000345E 668B93[D2650000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2743                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2744                              <1> 	; xor 	bx, bx ; 0
  2745 00003465 30DB                <1> 	xor	bl, bl ; 0
  2746                              <1> 		; clr r2
  2747 00003467 31F6                <1> 	xor	esi, esi ; 0
  2748                              <1> 		; clr r5 / initialize reg
  2749                              <1> sysexit_2: ; 1:
  2750                              <1> 	        ; / find children of this dying process, 
  2751                              <1> 		; / if they are zombies, free them
  2752                              <1> 	;add	bx, 2
  2753 00003469 80C302              <1> 	add	bl, 2
  2754                              <1> 		; add $2,r2 / search parent process table 
  2755                              <1> 		          ; / for dying process's name
  2756 0000346C 66398B[D2650000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2757                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2758 00003473 7513                <1> 	jne	short sysexit_4
  2759                              <1> 		; bne 3f / no
  2760                              <1> 	;shr	bx, 1
  2761 00003475 D0EB                <1> 	shr	bl, 1
  2762                              <1> 		; asr r2 / yes, it is a parent
  2763 00003477 80BB[13660000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2764                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2765                              <1> 				     ; / dying process a zombie
  2766 0000347E 7506                <1> 	jne	short sysexit_3 
  2767                              <1> 		; bne 2f / no
  2768 00003480 88A3[13660000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2769                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2770                              <1> sysexit_3: ; 2:
  2771                              <1> 	;shr	bx, 1
  2772 00003486 D0E3                <1> 	shl	bl, 1
  2773                              <1> 		; asl r2
  2774                              <1> sysexit_4: ; 3:
  2775                              <1> 		; / search the process name table 
  2776                              <1> 		; / for the dying process's parent
  2777 00003488 663993[B2650000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2778                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2779 0000348F 7502                <1> 	jne	short sysexit_5
  2780                              <1> 		; bne 3f / no
  2781 00003491 89DE                <1> 	mov	esi, ebx
  2782                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2783                              <1> 		          ; / process # x2) in r5
  2784                              <1> sysexit_5: ; 3:
  2785                              <1> 	;cmp	bx, nproc + nproc
  2786 00003493 80FB20              <1> 	cmp	bl, nproc + nproc
  2787                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2788 00003496 72D1                <1> 	jb	short sysexit_2
  2789                              <1> 		; blt 1b / no, go back
  2790                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2791 00003498 21F6                <1> 	and	esi, esi ; r5=r1
  2792 0000349A 7431                <1> 	jz	short sysexit_6
  2793                              <1> 		; beq 2f / no parent has been found. 
  2794                              <1> 		       ; / The process just dies
  2795 0000349C 66D1EE              <1> 	shr	si, 1
  2796                              <1> 		; asr r1 / set up index to p.stat
  2797 0000349F 8A86[13660000]      <1> 	mov	al, [esi+p.stat-1]
  2798                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2799 000034A5 20C0                <1> 	and	al, al
  2800 000034A7 7424                <1> 	jz	short sysexit_6
  2801                              <1> 		; beq 2f / if its been freed, 2f
  2802 000034A9 3C03                <1> 	cmp	al, 3
  2803                              <1> 		; cmp r2,$3 / is parent a zombie?
  2804 000034AB 7420                <1> 	je	short sysexit_6
  2805                              <1> 		; beq 2f / yes, 2f
  2806                              <1> 	; BH = 0
  2807 000034AD 8A1D[E7680000]      <1> 	mov	bl, [u.uno]
  2808                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2809 000034B3 C683[13660000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2810                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2811                              <1> 	; 05/02/2014
  2812 000034BA 3C01                <1> 	cmp	al, 1 ; SRUN
  2813 000034BC 740F                <1> 	je	short sysexit_6
  2814                              <1> 	;cmp	al, 2
  2815                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2816                              <1> 			  ; / this child to die
  2817                              <1> 	;jne	short sysexit_6	
  2818                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2819                              <1> 	; 05/02/2014
  2820                              <1> 	; p.stat = 2 --> waiting
  2821                              <1> 	; p.stat = 4 --> sleeping
  2822 000034BE C686[13660000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2823                              <1> 	;dec	byte [esi+p.stat-1]
  2824                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2825 000034C5 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2826                              <1> 	; 
  2827                              <1> 	;mov	ebx, runq + 4
  2828                              <1> 		; mov $runq+4,r2 / on the runq
  2829 000034C8 E8CF120000          <1> 	call	putlu
  2830                              <1> 		; jsr r0, putlu
  2831                              <1> sysexit_6: ; 2:
  2832                              <1> 	; 31/08/2015
  2833                              <1> 		; / the process dies
  2834 000034CD C605[E7680000]00    <1> 	mov	byte [u.uno], 0
  2835                              <1> 		; clrb u.uno / put zero as the process number, 
  2836                              <1> 	           ; / so "swap" will
  2837 000034D4 E8F6110000          <1> 	call	swap
  2838                              <1> 		; jsr r0,swap / overwrite process with another process
  2839                              <1> hlt_sys:
  2840                              <1> 	;sti ; 18/01/2014
  2841                              <1> hlts0:
  2842 000034D9 F4                  <1> 	hlt
  2843 000034DA EBFD                <1> 	jmp	short hlts0
  2844                              <1> 		; 0 / and thereby kill it; halt?
  2845                              <1> 
  2846                              <1> 
  2847                              <1> syswait: ; < wait for a processs to die >
  2848                              <1> 	; 09/02/2022
  2849                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2850                              <1> 	; 17/09/2015
  2851                              <1> 	; 02/09/2015
  2852                              <1> 	; 01/09/2015
  2853                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2854                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2855                              <1> 	;
  2856                              <1> 	; 'syswait' waits for a process die. 
  2857                              <1> 	; It works in following way:
  2858                              <1> 	;    1) From the parent process number, the parent's 
  2859                              <1> 	; 	process name is found. The p.ppid table of parent
  2860                              <1> 	;	names is then searched for this process name.
  2861                              <1> 	;	If a match occurs, r2 contains child's process
  2862                              <1> 	;	number. The child status is checked to see if it is
  2863                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2864                              <1> 	;	If it is, the child process is freed and it's name
  2865                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2866                              <1> 	;	If the child is not a zombie, nothing happens and
  2867                              <1> 	;	the search goes on through the p.ppid table until
  2868                              <1> 	;	all processes are checked or a zombie is found.
  2869                              <1> 	;    2) If no zombies are found, a check is made to see if
  2870                              <1> 	;	there are any children at all. If there are none,
  2871                              <1> 	;	an error return is made. If there are, the parent's
  2872                              <1> 	;	status is set to 2 (waiting for child to die),
  2873                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2874                              <1> 	;	is made to wait on the next process.
  2875                              <1> 	;
  2876                              <1> 	; Calling sequence:
  2877                              <1> 	;	?
  2878                              <1> 	; Arguments:
  2879                              <1> 	;	-
  2880                              <1> 	; Inputs: - 
  2881                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2882                              <1> 	; ...............................................................
  2883                              <1> 	;				
  2884                              <1> 	
  2885                              <1> ; / wait for a process to die
  2886                              <1> 
  2887                              <1> syswait_0:
  2888 000034DC 0FB61D[E7680000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2889                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2890 000034E3 D0E3                <1> 	shl	bl, 1
  2891                              <1> 	;shl	bx, 1
  2892                              <1> 		; asl r1 / x2 to get index into p.pid table
  2893 000034E5 668B83[B2650000]    <1> 	mov	ax, [ebx+p.pid-2]
  2894                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2895 000034EC 31F6                <1> 	xor	esi, esi
  2896                              <1> 		; clr r2
  2897 000034EE 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2898                              <1> 	;xor 	cl, cl
  2899                              <1> 		; clr r3 / initialize reg 3
  2900                              <1> syswait_1: ; 1:
  2901                              <1> 	; 09/02/2022
  2902 000034F0 46                  <1> 	inc	esi
  2903 000034F1 46                  <1> 	inc	esi
  2904                              <1> 	;add	si, 2
  2905                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2906                              <1> 			  ; / search table of parent processes 
  2907                              <1> 			  ; / for this process name
  2908 000034F2 663B86[D2650000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2909                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2910                              <1> 			            ; / process number
  2911 000034F9 7531                <1> 	jne	short syswait_3
  2912                              <1> 		;bne 3f / branch if no match of parent process name
  2913                              <1> 	;inc	cx
  2914 000034FB FEC1                <1> 	inc	cl
  2915                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2916                              <1> 	; 09/02/2022
  2917 000034FD D1EE                <1> 	shr	esi, 1
  2918                              <1> 	;shr	si, 1
  2919                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2920                              <1> 	; The possible states ('p.stat' values) of a process are:
  2921                              <1> 	;	0 = free or unused
  2922                              <1> 	;	1 = active
  2923                              <1> 	;	2 = waiting for a child process to die
  2924                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2925 000034FF 80BE[13660000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2926                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2927 00003506 7522                <1> 	jne	short syswait_2
  2928                              <1> 		; bne 2f / no, skip it
  2929 00003508 88BE[13660000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2930                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2931                              <1> 	; 09/02/2022
  2932 0000350E D1E6                <1> 	shl	esi, 1
  2933                              <1> 	;shl	si, 1
  2934                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2935 00003510 0FB786[B2650000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2936 00003517 A3[98680000]        <1> 	mov	[u.r0], eax
  2937                              <1> 		; mov p.pid-2(r2),*u.r0 
  2938                              <1> 			      ; / put childs process name in (u.r0)
  2939                              <1> 	;
  2940                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2941                              <1> 	;
  2942                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2943                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2944                              <1> 	; system call loop from the application/program if it calls
  2945                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2946                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2947                              <1> 	;
  2948                              <1> 	; Note: syswait will return with error if there is not a
  2949                              <1> 	;       zombie or running process to wait.	
  2950                              <1> 	;
  2951                              <1> 	;sub	ax, ax
  2952                              <1> 	; 08/01/2022
  2953 0000351C 29C0                <1> 	sub	eax, eax
  2954 0000351E 668986[D2650000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2955 00003525 E90AFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2956                              <1> 	;
  2957                              <1> 	;jmp	sysret
  2958                              <1> 		; br sysret1 / return cause child is dead
  2959                              <1> syswait_2: ; 2:
  2960                              <1> 	; 09/02/2022
  2961 0000352A D1E6                <1> 	shl	esi, 1
  2962                              <1> 	;shl	si, 1
  2963                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2964                              <1> syswait_3: ; 3:
  2965 0000352C 6683FE20            <1> 	cmp	si, nproc+nproc
  2966                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2967 00003530 72BE                <1> 	jb	short syswait_1
  2968                              <1> 		; blt 1b / no, continue search
  2969                              <1> 	;and	cx, cx
  2970 00003532 20C9                <1> 	and	cl, cl
  2971                              <1> 		; tst r3 / one gets here if there are no children 
  2972                              <1> 		       ; / or children that are still active
  2973                              <1> 	; 30/10/2013
  2974 00003534 7515                <1> 	jnz	short syswait_4
  2975                              <1> 	;jz	error
  2976                              <1> 		; beq error1 / there are no children, error
  2977 00003536 890D[98680000]      <1> 	mov	[u.r0], ecx ; 0
  2978                              <1> 	; 09/02/2022
  2979 0000353C C705[ED680000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2979 00003544 0000                <1>
  2980                              <1> 			; miscellaneous/other errors
  2981 00003546 E9C7FDFFFF          <1> 	jmp	error
  2982                              <1> syswait_4:
  2983 0000354B 8A1D[E7680000]      <1> 	mov	bl, [u.uno]
  2984                              <1> 		; movb u.uno,r1 / there are children so put 
  2985                              <1> 			      ; / parent process number in r1
  2986 00003551 FE83[13660000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2987                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2988                              <1> 				  ; / other children to die
  2989                              <1> 	; 04/11/2013
  2990 00003557 E873110000          <1> 	call	swap
  2991                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2992 0000355C E97BFFFFFF          <1> 	jmp	syswait_0
  2993                              <1> 		; br syswait / wait on next process
  2994                              <1> 
  2995                              <1> sysfork: ; < create a new process >
  2996                              <1> 	; 26/02/2022
  2997                              <1> 	; 25/02/2022
  2998                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2999                              <1> 	; 18/09/2015
  3000                              <1> 	; 04/09/2015
  3001                              <1> 	; 02/09/2015
  3002                              <1> 	; 01/09/2015
  3003                              <1> 	; 28/08/2015
  3004                              <1> 	; 14/05/2015
  3005                              <1> 	; 10/05/2015
  3006                              <1> 	; 09/05/2015
  3007                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  3008                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  3009                              <1> 	;
  3010                              <1> 	; 'sysfork' creates a new process. This process is referred
  3011                              <1> 	; to as the child process. This new process core image is
  3012                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  3013                              <1> 	; distinction is the return location and the fact that (u.r0)
  3014                              <1> 	; in the old process (parent) contains the process id (p.pid)
  3015                              <1> 	; of the new process (child). This id is used by 'syswait'.
  3016                              <1> 	; 'sysfork' works in the following manner: 	
  3017                              <1> 	;    1) The process status table (p.stat) is searched to find
  3018                              <1> 	;	a process number that is unused. If none are found
  3019                              <1> 	;	an error occurs.
  3020                              <1> 	;    2) when one is found, it becomes the child process number
  3021                              <1> 	;	and it's status (p.stat) is set to active.
  3022                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3023                              <1> 	;	character in that tty buffer is cleared.
  3024                              <1> 	;    4) The child process is put on the lowest priority run 
  3025                              <1> 	;	queue via 'putlu'.
  3026                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3027                              <1> 	;	it is a unique number) and is put in the child's unique
  3028                              <1> 	;	identifier; process id (p.pid).
  3029                              <1> 	;    6) The process name of the parent is then obtained and
  3030                              <1> 	;	placed in the unique identifier of the parent process
  3031                              <1> 	;	name is then put in 'u.r0'.	
  3032                              <1> 	;    7) The child process is then written out on disk by
  3033                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3034                              <1> 	;	and the child is born. (The child process is written 
  3035                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3036                              <1> 	;	number.)
  3037                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3038                              <1> 	;    9) The child process name is put in 'u.r0'.
  3039                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3040                              <1> 	;	create the return address for the parent process.
  3041                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3042                              <1> 	;	the parent has opened. For each file the parent has
  3043                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3044                              <1> 	;	to indicate that the child process also has opened
  3045                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3046                              <1> 	;
  3047                              <1> 	; Calling sequence:
  3048                              <1> 	;	from shell ?
  3049                              <1> 	; Arguments:
  3050                              <1> 	;	-
  3051                              <1> 	; Inputs: -
  3052                              <1> 	; Outputs: *u.r0 - child process name
  3053                              <1> 	; ...............................................................
  3054                              <1> 	;	
  3055                              <1> 	; Retro UNIX 8086 v1 modification: 
  3056                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3057                              <1> 	;	= process id of child a parent process returns
  3058                              <1> 	;	= process id of parent when a child process returns
  3059                              <1> 	;
  3060                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3061                              <1> 	;	in following manner: (with an example: c library, fork)
  3062                              <1> 	;	
  3063                              <1> 	;	1:
  3064                              <1> 	;		sys	fork
  3065                              <1> 	;			br 1f  / child process returns here
  3066                              <1> 	;		bes	2f     / parent process returns here
  3067                              <1> 	;		/ pid of new process in r0
  3068                              <1> 	;		rts	pc
  3069                              <1> 	;	2: / parent process condionally branches here
  3070                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3071                              <1> 	;		rts	pc
  3072                              <1> 	;
  3073                              <1> 	;	1: / child process brances here
  3074                              <1> 	;		clr	r0   / pid = 0 in child process
  3075                              <1> 	;		rts	pc
  3076                              <1> 	;
  3077                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3078                              <1> 	;		// pid = fork();
  3079                              <1> 	;		//
  3080                              <1> 	;		// pid == 0 in child process; 
  3081                              <1> 	;		// pid == -1 means error return
  3082                              <1> 	;		// in child, 
  3083                              <1> 	;		//	parents id is in par_uid if needed
  3084                              <1> 	;		
  3085                              <1> 	;		_fork:
  3086                              <1> 	;			mov	$.fork,eax
  3087                              <1> 	;			int	$0x30
  3088                              <1> 	;			jmp	1f
  3089                              <1> 	;			jnc	2f
  3090                              <1> 	;			jmp	cerror
  3091                              <1> 	;		1:
  3092                              <1> 	;			mov	eax,_par_uid
  3093                              <1> 	;			xor	eax,eax
  3094                              <1> 	;		2:
  3095                              <1> 	;			ret
  3096                              <1> 	;
  3097                              <1> 	;	In Retro UNIX 8086 v1,
  3098                              <1> 	;	'sysfork' returns in following manner:
  3099                              <1> 	;	
  3100                              <1> 	;		mov	ax, sys_fork
  3101                              <1> 	;		mov	bx, offset @f ; routine for child
  3102                              <1> 	;		int	20h
  3103                              <1> 	;		jc	error
  3104                              <1> 	;		
  3105                              <1> 	;	; Routine for parent process here (just after 'jc')
  3106                              <1> 	;		mov	word ptr [pid_of_child], ax
  3107                              <1> 	;		jmp	next_routine_for_parent	
  3108                              <1> 	;
  3109                              <1> 	;	@@: ; routine for child process here				
  3110                              <1> 	;		....	
  3111                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3112                              <1> 	;	       for child process by using BX input.
  3113                              <1> 	;	      (at first, parent process will return then 
  3114                              <1> 	;	      child process will return -after swapped in-
  3115                              <1> 	;	      'syswait' is needed in parent process
  3116                              <1> 	;	      if return from child process will be waited for.)
  3117                              <1> 	;	  				
  3118                              <1> 	
  3119                              <1> ; / create a new process
  3120                              <1> 	; EBX = return address for child process 
  3121                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3122 00003561 31F6                <1> 	xor 	esi, esi
  3123                              <1> 		; clr r1
  3124                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3125 00003563 46                  <1> 	inc	esi
  3126                              <1> 		; inc r1
  3127 00003564 80BE[13660000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3128                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3129 0000356B 760B                <1> 	jna	short sysfork_2	
  3130                              <1> 		; beq 1f / it's unused so branch
  3131 0000356D 6683FE10            <1> 	cmp	si, nproc
  3132                              <1> 		; cmp r1,$nproc / all processes checked
  3133 00003571 72F0                <1> 	jb	short sysfork_1
  3134                              <1> 		; blt 1b / no, branch back
  3135                              <1> 	;
  3136                              <1> 	; Retro UNIX 8086 v1. modification:
  3137                              <1> 	;	Parent process returns from 'sysfork' to address 
  3138                              <1> 	;	which is just after 'sysfork' system call in parent
  3139                              <1> 	;	process. Child process returns to address which is put
  3140                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3141                              <1> 	;
  3142                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3143                              <1> 		             ; / to old process return
  3144                              <1> 		; br error1 / no room for a new process
  3145                              <1> sysfork_0:
  3146 00003573 E99AFDFFFF          <1> 	jmp	error
  3147                              <1> sysfork_2: ; 1:
  3148 00003578 E884F0FFFF          <1> 	call	allocate_page
  3149                              <1> 	;jc	error
  3150                              <1> 	; 08/01/2022
  3151 0000357D 72F4                <1> 	jc	short sysfork_0
  3152                              <1> 
  3153 0000357F 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3154                              <1> 	; Retro UNIX 386 v1 modification!
  3155 00003580 E875F2FFFF          <1> 	call	duplicate_page_dir
  3156                              <1> 		; EAX = New page directory 
  3157 00003585 7308                <1> 	jnc	short sysfork_3
  3158 00003587 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3159 00003588 E83CF2FFFF          <1> 	call 	deallocate_page
  3160                              <1> 	;jmp	error
  3161                              <1> 	; 08/01/2022
  3162 0000358D EBE4                <1> 	jmp	short sysfork_0 ; error
  3163                              <1> sysfork_3:
  3164                              <1> 	; Retro UNIX 386 v1 modification !
  3165 0000358F 56                  <1> 	push	esi
  3166 00003590 E8B1110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3167                              <1> 		      ; and interrupt return components (for IRET)
  3168 00003595 8705[F1680000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3169 0000359B A3[F5680000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3170 000035A0 5E                  <1> 	pop	esi
  3171 000035A1 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3172                              <1> 		; [u.usp] = esp
  3173 000035A2 89F7                <1> 	mov	edi, esi
  3174                              <1> 	;shl	di, 2
  3175                              <1> 	; 08/01/2022
  3176 000035A4 C1E702              <1> 	shl	edi, 2
  3177 000035A7 8987[20660000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3178 000035AD A3[E8680000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3179                              <1> 	; 28/08/2015
  3180 000035B2 0FB605[E7680000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3181                              <1> 		; movb u.uno,-(sp) / save parent process number
  3182 000035B9 89C7                <1> 	mov	edi, eax
  3183 000035BB 50                  <1>         push	eax ; ** 
  3184 000035BC 8A87[F3650000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3185                              <1> 		; 18/09/2015
  3186 000035C2 8886[F3650000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3187                              <1> 	; 26/02/2022 (p.waitc is not used)
  3188                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3189                              <1> 	; 25/02/2022 (BugFix)
  3190                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3191                              <1> 	;			   ; ah - reset child's wait channel	
  3192 000035C8 89F0                <1> 	mov	eax, esi
  3193 000035CA A2[E7680000]        <1> 	mov	[u.uno], al ; child process number
  3194                              <1> 		;movb r1,u.uno / set child process number to r1
  3195 000035CF FE86[13660000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3196                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3197                              <1> 				; / process to active status
  3198                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3199                              <1> 			      ; / control tty buffer in r2
  3200                              <1>                 ; beq 2f / branch, if no such tty assigned
  3201                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3202                              <1> 	; 2:
  3203 000035D5 53                  <1> 	push	ebx  ; * return address for the child process
  3204                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3205                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3206                              <1> 		; mov $runq+4,r2
  3207 000035D6 E8C1110000          <1> 	call	putlu 
  3208                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3209                              <1> 			   ; / run queue
  3210                              <1> 	; 08/01/2022
  3211 000035DB D1E6                <1> 	shl	esi, 1
  3212                              <1> 	;shl	si, 1
  3213                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3214                              <1> 		       ; / into p.pid table
  3215 000035DD 66FF05[84680000]    <1> 	inc	word [mpid]
  3216                              <1> 		; inc mpid / increment m.pid; get a new process name
  3217 000035E4 66A1[84680000]      <1> 	mov	ax, [mpid]
  3218 000035EA 668986[B2650000]    <1> 	mov	[esi+p.pid-2], ax
  3219                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3220                              <1> 				    ; / in child process' name slot
  3221 000035F1 5A                  <1> 	pop	edx  ; * return address for the child process
  3222                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3223 000035F2 5B                  <1>   	pop	ebx  ; **
  3224                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3225                              <1> 		; movb (sp),r2 / put parent process number in r2
  3226                              <1> 	; 08/01/2022
  3227 000035F3 D1E3                <1> 	shl	ebx, 1
  3228                              <1> 	;shl 	bx, 1
  3229                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3230                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3231 000035F5 668B83[B2650000]    <1> 	mov	ax, [ebx+p.pid-2]
  3232                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3233                              <1> 				   ; / process
  3234 000035FC 668986[D2650000]    <1> 	mov	[esi+p.ppid-2], ax
  3235                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3236                              <1> 			  ; / in parent process slot for child
  3237 00003603 A3[98680000]        <1> 	mov	[u.r0], eax	
  3238                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3239                              <1> 			     ; / at location where r0 was saved
  3240 00003608 8B2D[90680000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3241 0000360E 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3242                              <1> 			   ; * return address for the child process
  3243                              <1> 		; mov $sysret1,-(sp) /
  3244                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3245                              <1> 			      ; / user is swapped out
  3246                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3247                              <1> 	; 04/09/2015 - 01/09/2015
  3248                              <1> 	; [u.usp] = esp
  3249 00003611 68[32330000]        <1> 	push	sysret ; ***
  3250 00003616 8925[94680000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3251                              <1> 			     ; (for child process)	
  3252 0000361C 31C0                <1> 	xor 	eax, eax
  3253 0000361E 66A3[C8680000]      <1> 	mov 	[u.ttyp], ax ; 0
  3254                              <1> 	;
  3255 00003624 E81D110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3256                              <1> 		;jsr r0,wswap / put child process out on drum
  3257                              <1> 		;jsr r0,unpack / unpack user stack
  3258                              <1> 		;mov u.usp,sp / restore user stack pointer
  3259                              <1> 		; tst (sp)+ / bump stack pointer
  3260                              <1> 	; Retro UNIX 386 v1 modification !
  3261 00003629 58                  <1> 	pop	eax ; ***
  3262                              <1> 	; 08/01/2022
  3263 0000362A D1E3                <1> 	shl	ebx, 1
  3264                              <1> 	;shl 	bx, 1
  3265 0000362C 8B83[20660000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3266 00003632 E838110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3267                              <1> 		      ; registers and return address (for IRET)
  3268                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3269 00003637 0FB705[84680000]    <1>         movzx   eax, word [mpid]
  3270 0000363E A3[98680000]        <1> 	mov	[u.r0], eax
  3271                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3272                              <1> 			       ; / where r0 was saved
  3273                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3274                              <1> 			          ; / process return
  3275                              <1> 	;xor	ebx, ebx
  3276 00003643 31F6                <1> 	xor     esi, esi
  3277                              <1> 		;clr r1
  3278                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3279                              <1> 	      ; / opened by the parent process
  3280                              <1> 	; 01/09/2015
  3281                              <1> 	;xor	bh, bh
  3282                              <1> 	;mov 	bl, [esi+u.fp]
  3283 00003645 8A86[9E680000]      <1> 	mov 	al, [esi+u.fp]
  3284                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3285                              <1>         ;or	bl, bl
  3286 0000364B 08C0                <1> 	or	al, al
  3287 0000364D 740C                <1> 	jz	short sysfork_5	
  3288                              <1> 		; beq 2f / file has not been opened by parent, 
  3289                              <1> 		       ; / so branch
  3290 0000364F B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3291 00003651 F6E4                <1> 	mul	ah
  3292                              <1> 	;;movzx	ebx, ax
  3293                              <1> 	;mov	bx, ax
  3294 00003653 89C3                <1> 	mov	ebx, eax ; 08/01/2022
  3295                              <1> 	;shl	bx, 3
  3296                              <1> 		; asl r2 / multiply by 8
  3297                              <1>        		; asl r2 / to get index into fsp table
  3298                              <1>        		; asl r2
  3299 00003655 FE83[62660000]      <1>   	inc     byte [ebx+fsp-2]
  3300                              <1> 		; incb fsp-2(r2) / increment number of processes
  3301                              <1> 			     ; / using file, because child will now be
  3302                              <1> 			     ; / using this file
  3303                              <1> sysfork_5: ; 2:
  3304 0000365B 46                  <1>         inc     esi
  3305                              <1> 		; inc r1 / get next open file
  3306 0000365C 6683FE0A            <1>         cmp     si, 10
  3307                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3308                              <1> 			  ; / can be opened
  3309 00003660 72E3                <1> 	jb	short sysfork_4	
  3310                              <1> 		; blt 1b / check next entry
  3311 00003662 E9CBFCFFFF          <1> 	jmp	sysret
  3312                              <1> 		; br sysret1
  3313                              <1> 
  3314                              <1> sysread: ; < read from file >
  3315                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3316                              <1> 	; 13/05/2015
  3317                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3318                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3319                              <1> 	;
  3320                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3321                              <1> 	; characters to be read. If finds the file from the file
  3322                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3323                              <1> 	; is returned from a successful open call (sysopen).
  3324                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3325                              <1> 	; is read into core via 'readi'.
  3326                              <1> 	;
  3327                              <1> 	; Calling sequence:
  3328                              <1> 	;	sysread; buffer; nchars
  3329                              <1> 	; Arguments:
  3330                              <1> 	;	buffer - location of contiguous bytes where 
  3331                              <1> 	;		 input will be placed.
  3332                              <1> 	;	nchars - number of bytes or characters to be read.
  3333                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3334                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3335                              <1> 	; ...............................................................
  3336                              <1> 	;				
  3337                              <1> 	; Retro UNIX 8086 v1 modification: 
  3338                              <1> 	;       'sysread' 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 read. 
  3345                              <1> 	;
  3346 00003667 E840000000          <1> 	call	rw1
  3347                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3348                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3349                              <1>        	; 24/12/2021
  3350 0000366C 7239                <1> 	jc	short sysread_err
  3351 0000366E F6C480              <1> 	test	ah, 80h
  3352                              <1> 		; tst r1 / negative i-number?
  3353 00003671 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3354                              <1> 	;jnz	error
  3355                              <1> 		; ble error1 / yes, error 1 to read
  3356                              <1> 			   ; / it should be positive
  3357 00003673 E88B150000          <1> 	call	readi
  3358                              <1> 		; jsr r0,readi / read data into core
  3359 00003678 EB14                <1> 	jmp	short rw0
  3360                              <1> 		; br 1f
  3361                              <1> 
  3362                              <1> syswrite: ; < write to file >
  3363                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3364                              <1> 	; 13/05/2015
  3365                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3366                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3367                              <1> 	;
  3368                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3369                              <1> 	; and the number of characters to write. If finds the file
  3370                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3371                              <1> 	; descriptor is returned from a successful open or create call
  3372                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3373                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3374                              <1> 	;
  3375                              <1> 	; Calling sequence:
  3376                              <1> 	;	syswrite; buffer; nchars
  3377                              <1> 	; Arguments:
  3378                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3379                              <1> 	;	nchars - number of characters to be written.
  3380                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3381                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3382                              <1> 	; ...............................................................
  3383                              <1> 	;				
  3384                              <1> 	; Retro UNIX 8086 v1 modification: 
  3385                              <1> 	;       'syswrite' system call has three arguments; so,
  3386                              <1> 	;	* 1st argument, file descriptor is in BX register
  3387                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3388                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3389                              <1> 	;
  3390                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3391                              <1> 	;	to the user with number of bytes written. 
  3392                              <1> 	;
  3393 0000367A E82D000000          <1> 	call	rw1
  3394                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3395                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3396                              <1>        	; 24/12/2021
  3397 0000367F 7226                <1> 	jc	short syswrite_err
  3398 00003681 F6C480              <1>         test	ah, 80h
  3399                              <1> 		; tst r1 / positive i-number ?
  3400 00003684 7417                <1>         jz	short rw3 ; 13/05/2015
  3401                              <1> 	;jz	error
  3402                              <1> 		; bge error1 / yes, error 1 
  3403                              <1> 			   ; / negative i-number means write
  3404 00003686 66F7D8              <1>         neg	ax
  3405                              <1> 		; neg r1 / make it positive
  3406 00003689 E863170000          <1> 	call	writei
  3407                              <1>         	; jsr r0,writei / write data
  3408                              <1> rw0: ; 1:
  3409 0000368E A1[C0680000]        <1>         mov	eax, [u.nread]
  3410 00003693 A3[98680000]        <1> 	mov	[u.r0], eax
  3411                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3412                              <1> 				  ; / into (u.r0)
  3413 00003698 E995FCFFFF          <1> 	jmp	sysret
  3414                              <1>         	; br sysret1
  3415                              <1> 
  3416                              <1> rw3: 
  3417                              <1> 	; 13/05/2015
  3418 0000369D C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3418 000036A5 0000                <1>
  3419                              <1> 	;stc
  3420                              <1> 	;retn
  3421                              <1> 	; 24/12/2021 (BugFix)
  3422                              <1> sysread_err:
  3423                              <1> syswrite_err:
  3424 000036A7 E966FCFFFF          <1> 	jmp	error
  3425                              <1> 
  3426                              <1> rw1:	
  3427                              <1> 	; 14/05/2015
  3428                              <1> 	; 13/05/2015
  3429                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3430                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3431                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3432                              <1> 	;
  3433                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3434                              <1> 				;(in the user's virtual memory space)
  3435                              <1> 	;mov	[u.count], edx 
  3436                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3437                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3438                              <1> 	;;mov	eax, ebx ; file descriptor
  3439                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3440                              <1> 		             ; / (index to u.fp table) in r1
  3441                              <1> 	; 13/05/2015
  3442 000036AC C705[98680000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3442 000036B4 0000                <1>
  3443                              <1> 	;
  3444                              <1> 	;; call	getf
  3445                              <1>         ; eBX = File descriptor
  3446 000036B6 E8330B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3447                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3448                              <1> 	; AX = I-number of the file ; negative i-number means write
  3449                              <1> 	; 13/05/2015
  3450 000036BB 6683F801            <1> 	cmp 	ax, 1
  3451 000036BF 7217                <1> 	jb	short rw2
  3452                              <1> 	;
  3453 000036C1 890D[B8680000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3454                              <1> 				;(in the user's virtual memory space)
  3455 000036C7 8915[BC680000]      <1> 	mov	[u.count], edx 
  3456                              <1> 	; 14/05/2015
  3457 000036CD C705[ED680000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3457 000036D5 0000                <1>
  3458 000036D7 C3                  <1> 	retn
  3459                              <1>         	; rts r0
  3460                              <1> rw2:
  3461                              <1> 	; 13/05/2015
  3462 000036D8 C705[ED680000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3462 000036E0 0000                <1>
  3463 000036E2 C3                  <1> 	retn
  3464                              <1> 
  3465                              <1> sysopen: ;<open file>
  3466                              <1> 	; 09/01/2022
  3467                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3468                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3469                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3470                              <1> 	;
  3471                              <1> 	; 'sysopen' opens a file in following manner:
  3472                              <1> 	;    1) The second argument in a sysopen says whether to
  3473                              <1> 	;	open the file ro read (0) or write (>0).
  3474                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3475                              <1> 	;    3) The file is opened by 'iopen'.
  3476                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3477                              <1> 	;	and the user's open file list - u.fp.
  3478                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3479                              <1> 	;	b) An entry for the file is created in the fsp table.
  3480                              <1> 	;	c) The number of this entry is put on u.fp list.
  3481                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3482                              <1> 	;	   to by u.r0.
  3483                              <1> 	;
  3484                              <1> 	; Calling sequence:
  3485                              <1> 	;	sysopen; name; mode
  3486                              <1> 	; Arguments:
  3487                              <1> 	;	name - file name or path name
  3488                              <1> 	;	mode - 0 to open for reading
  3489                              <1> 	;	       1 to open for writing
  3490                              <1> 	; Inputs: (arguments)
  3491                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3492                              <1> 	;		  is put into r0's location on the stack.	
  3493                              <1> 	; ...............................................................
  3494                              <1> 	;				
  3495                              <1> 	; Retro UNIX 8086 v1 modification: 
  3496                              <1> 	;       'sysopen' system call has two arguments; so,
  3497                              <1> 	;	* 1st argument, name is pointed to by BX register
  3498                              <1> 	;	* 2nd argument, mode is in CX register
  3499                              <1> 	;
  3500                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3501                              <1> 	;	to the user with the file descriptor/number 
  3502                              <1> 	;	(index to u.fp list).
  3503                              <1> 	;
  3504                              <1> 	;call	arg2
  3505                              <1> 	; * name - 'u.namep' points to address of file/path name
  3506                              <1> 	;          in the user's program segment ('u.segmnt')
  3507                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3508                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3509                              <1> 	;          which is on top of stack.
  3510                              <1> 	;
  3511                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3512                              <1> 	;
  3513                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3514                              <1> 
  3515 000036E3 891D[B0680000]      <1> 	mov	[u.namep], ebx
  3516                              <1> 	; 24/12/2021 (cx -> ecx)
  3517 000036E9 51                  <1> 	push	ecx ; * 
  3518 000036EA E8300B0000          <1> 	call	namei
  3519                              <1> 		; jsr r0,namei / i-number of file in r1
  3520                              <1>      	;and	ax, ax
  3521                              <1> 	;jz	error ; File not found
  3522 000036EF 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3523                              <1> 	;jc	error ; 27/05/2013
  3524                              <1> 		; br  error2 / file not found
  3525                              <1>    	; 24/12/2021
  3526                              <1> 	;pop	edx ; * ; mode
  3527                              <1> 	;push	edx ; *
  3528 000036F1 8B1424              <1> 	mov	edx, [esp] ; *
  3529                              <1> 	; edx = open mode (0 or 1)
  3530                              <1> 	;or	dx, dx
  3531 000036F4 08D2                <1> 	or	dl, dl
  3532                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3533                              <1> 		         ; / 0 means, open for read)
  3534 000036F6 7403                <1> 	jz	short sysopen_0
  3535                              <1> 		; beq 1f / yes, leave i-number positive
  3536                              <1> syscreat_0: ; 27/12/2015
  3537 000036F8 66F7D8              <1> 	neg	ax
  3538                              <1>         	; neg r1 / open for writing so make i-number negative
  3539                              <1> sysopen_0: ;1:
  3540 000036FB E8891B0000          <1> 	call	iopen
  3541                              <1> 		;jsr r0,iopen / open file whose i-number is in r1
  3542 00003700 5A                  <1> 	pop	edx ; * ; mode ; 24/12/2021
  3543                              <1> 	;and	dx, dx
  3544 00003701 20D2                <1> 	and	dl, dl
  3545                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3546 00003703 7403                <1> 	jz	short sysopen_2
  3547                              <1>         	; beq op1 / is open for read op1
  3548                              <1> sysopen_1: ;op0:
  3549 00003705 66F7D8              <1> 	neg	ax
  3550                              <1>         	; neg r1 
  3551                              <1> 	;; NOTE: iopen always make i-number positive.
  3552                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3553                              <1> sysopen_2: ;op1:
  3554 00003708 31F6                <1>         xor     esi, esi
  3555                              <1>         	; clr r2 / clear registers
  3556 0000370A 31DB                <1>         xor     ebx, ebx
  3557                              <1> 		; clr r3
  3558                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3559 0000370C 389E[9E680000]      <1>         cmp     [esi+u.fp], bl ; 0
  3560                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3561 00003712 7625                <1>         jna      short sysopen_4
  3562                              <1> 		; beq 1f / if byte in list is 0 branch
  3563 00003714 46                  <1>         inc     esi
  3564                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3565 00003715 6683FE0A            <1>         cmp     si, 10  ; OPENFILES
  3566                              <1> 		; cmp r2,$10. / reached end of list?
  3567 00003719 72F1                <1> 	jb	short sysopen_3
  3568                              <1> 		; blt 1b / no, go back
  3569                              <1> toomanyf:
  3570                              <1> 	; 14/05/2015
  3571 0000371B C705[ED680000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3571 00003723 0000                <1>
  3572 00003725 E9E8FBFFFF          <1> 	jmp	error
  3573                              <1>         	; br error2 / yes, error (no files open)
  3574                              <1> fnotfound: 
  3575                              <1> 	; 14/05/2015
  3576 0000372A C705[ED680000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3576 00003732 0000                <1>
  3577 00003734 E9D9FBFFFF          <1> 	jmp	error
  3578                              <1> 
  3579                              <1> sysopen_4: ; 1:
  3580 00003739 6683BB[64660000]00  <1>         cmp     word [ebx+fsp], 0
  3581                              <1> 		; tst fsp(r3) / scan fsp entries
  3582 00003741 760D                <1>         jna     short sysopen_5
  3583                              <1> 		; beq 1f / if 0 branch
  3584                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3585 00003743 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3586                              <1> 		; add $8.,r3 / add 8 to r3 
  3587                              <1> 			; / to bump it to next entry mfsp table
  3588 00003747 6681FBF401          <1>         cmp     bx, nfiles*10
  3589                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3590 0000374C 72EB                <1> 	jb	short sysopen_4
  3591                              <1>        		; blt 1b / no, back
  3592                              <1> 	;jmp	error
  3593                              <1>         ;	; br error2 / yes, error
  3594                              <1> 	; 24/12/2021
  3595 0000374E EBCB                <1> 	jmp	short toomanyf
  3596                              <1> 
  3597                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3598 00003750 668983[64660000]    <1>         mov     [ebx+fsp], ax
  3599                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3600                              <1> 			; / into next available entry in fsp table,
  3601                              <1> 	; 09/01/2022
  3602                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3603                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3604                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3605                              <1> 	;xor	edi, edi
  3606                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3607                              <1> 	;	; clr fsp+4(r3)
  3608                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3609                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3610 00003757 31C0                <1> 	xor	eax, eax
  3611 00003759 8983[68660000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3612 0000375F 668983[6C660000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3613                              <1> 
  3614 00003766 A0[7B680000]        <1> 	mov	al, [cdev]
  3615 0000376B 668983[66660000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3616                              <1> 
  3617 00003772 89D8                <1>   	mov	eax, ebx
  3618 00003774 B30A                <1> 	mov	bl, 10
  3619 00003776 F6F3                <1> 	div	bl 
  3620                              <1> 		; asr r3
  3621                              <1> 		; asr r3 / divide by 8 
  3622                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3623 00003778 FEC0                <1> 	inc	al
  3624                              <1>         	; inc r3 / add 1 to get fsp entry number
  3625 0000377A 8886[9E680000]      <1>         mov     [esi+u.fp], al
  3626                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3627                              <1> 			; / next available slot in u.fp list
  3628 00003780 8935[98680000]      <1>         mov     [u.r0], esi
  3629                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3630                              <1> 			     ; / into r0 loc on stack
  3631 00003786 E9A7FBFFFF          <1>         jmp	sysret
  3632                              <1> 		; br sysret2
  3633                              <1> 
  3634                              <1> 	;
  3635                              <1> 	; 'fsp' table (10 bytes/entry)
  3636                              <1> 	; bit 15				   bit 0
  3637                              <1> 	; ---|-------------------------------------------
  3638                              <1> 	; r/w|		i-number of open file
  3639                              <1> 	; ---|-------------------------------------------
  3640                              <1> 	;		   device number
  3641                              <1> 	; -----------------------------------------------
  3642                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3643                              <1> 	; -----------------------------------------------
  3644                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3645                              <1> 	; ----------------------|------------------------
  3646                              <1> 	;  flag that says file 	| number of processes
  3647                              <1> 	;   has been deleted	| that have file open 
  3648                              <1> 	; ----------------------|------------------------
  3649                              <1> 	;
  3650                              <1> 
  3651                              <1> syscreat: ; < create file >
  3652                              <1> 	; 24/12/2021
  3653                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3654                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3655                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3656                              <1> 	;
  3657                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3658                              <1> 	; u.namep points to name of the file and mode is put
  3659                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3660                              <1> 	; If the file aready exists, it's mode and owner remain 
  3661                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3662                              <1> 	; did not exist, an i-node is created with the new mode via
  3663                              <1> 	; 'maknod' whether or not the file already existed, it is
  3664                              <1> 	; open for writing. The fsp table is then searched for a free
  3665                              <1> 	; entry. When a free entry is found, proper data is placed
  3666                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3667                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3668                              <1> 	; is put in the user's r0. 			
  3669                              <1> 	;
  3670                              <1> 	; Calling sequence:
  3671                              <1> 	;	syscreate; name; mode
  3672                              <1> 	; Arguments:
  3673                              <1> 	;	name - name of the file to be created
  3674                              <1> 	;	mode - mode of the file to be created
  3675                              <1> 	; Inputs: (arguments)
  3676                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3677                              <1> 	;		   (the file descriptor of new file)
  3678                              <1> 	; ...............................................................
  3679                              <1> 	;				
  3680                              <1> 	; Retro UNIX 8086 v1 modification: 
  3681                              <1> 	;       'syscreate' system call has two arguments; so,
  3682                              <1> 	;	* 1st argument, name is pointed to by BX register
  3683                              <1> 	;	* 2nd argument, mode is in CX register
  3684                              <1> 	;
  3685                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3686                              <1> 	;	to the user with the file descriptor/number 
  3687                              <1> 	;	(index to u.fp list).
  3688                              <1> 	;
  3689                              <1> 	;call	arg2
  3690                              <1> 	; * name - 'u.namep' points to address of file/path name
  3691                              <1> 	;          in the user's program segment ('u.segmnt')
  3692                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3693                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3694                              <1> 	;          which is on top of stack.
  3695                              <1> 	;
  3696                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3697                              <1> 			    ; / on stack
  3698 0000378B 891D[B0680000]      <1> 	mov	[u.namep], ebx ; file name address
  3699                              <1> 	;push	cx ; mode
  3700                              <1> 	; 24/12/2021
  3701 00003791 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3702 00003792 E8880A0000          <1> 	call 	namei        	
  3703                              <1> 		; jsr r0,namei / get the i-number
  3704                              <1>         ;and	ax, ax
  3705                              <1> 	;jz	short syscreat_2	       	
  3706 00003797 721B                <1> 	jc	short syscreat_2
  3707                              <1> 		; br  2f / if file doesn't exist 2f
  3708                              <1> 	; 27/12/2015
  3709 00003799 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3710                              <1>         ;jb	syscreat_0 ; yes
  3711                              <1> 	; 24/12/2021
  3712 0000379D 7305                <1> 	jnb	short syscreat_1
  3713 0000379F E954FFFFFF          <1> 	jmp	syscreat_0
  3714                              <1> syscreat_1:
  3715 000037A4 66F7D8              <1> 	neg 	ax
  3716                              <1>         	; neg r1 / if file already exists make i-number 
  3717                              <1> 		       ; / negative (open for writing)
  3718 000037A7 E8DD1A0000          <1> 	call	iopen
  3719                              <1>         	; jsr r0,iopen /
  3720 000037AC E8AA130000          <1> 	call	itrunc
  3721                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3722                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3723                              <1> 	; 04/12/2021
  3724 000037B1 59                  <1> 	pop	ecx
  3725                              <1> 	; 08/01/2022
  3726 000037B2 EB0E                <1> 	jmp	short syscreat_3
  3727                              <1>         ;jmp	sysopen_1
  3728                              <1>         	; br op0
  3729                              <1> syscreat_2: ; 2: / file doesn't exist
  3730                              <1> 	;pop	ax
  3731                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3732                              <1> 	; 24/12/2021
  3733 000037B4 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3734 000037B5 30E4                <1> 	xor	ah, ah	
  3735                              <1>         	; bic $!377,r1 / clear upper byte
  3736 000037B7 E86F0D0000          <1> 	call 	maknod
  3737                              <1>         	; jsr r0,maknod / make an i-node for this file
  3738 000037BC 66A1[CA680000]      <1> 	mov	ax, [u.dirbuf]
  3739                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3740                              <1> 			        ; / for this new file in r1
  3741                              <1> syscreat_3:
  3742 000037C2 E93EFFFFFF          <1>         jmp     sysopen_1
  3743                              <1>         	; br op0 / open the file
  3744                              <1> 
  3745                              <1> sysmkdir: ; < make directory >
  3746                              <1> 	; 26/02/2022
  3747                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3748                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3749                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3750                              <1> 	;
  3751                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3752                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3753                              <1> 	; The special entries '.' and '..' are not present.
  3754                              <1> 	; Errors are indicated if the directory already exists or		
  3755                              <1> 	; user is not the super user. 
  3756                              <1> 	;
  3757                              <1> 	; Calling sequence:
  3758                              <1> 	;	sysmkdir; name; mode
  3759                              <1> 	; Arguments:
  3760                              <1> 	;	name - points to the name of the directory
  3761                              <1> 	;	mode - mode of the directory
  3762                              <1> 	; Inputs: (arguments)
  3763                              <1> 	; Outputs: -
  3764                              <1> 	;    (sets 'directory' flag to 1; 
  3765                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3766                              <1> 	; ...............................................................
  3767                              <1> 	;				
  3768                              <1> 	; Retro UNIX 8086 v1 modification: 
  3769                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3770                              <1> 	;	* 1st argument, name is pointed to by BX register
  3771                              <1> 	;	* 2nd argument, mode is in CX register
  3772                              <1> 	;
  3773                              <1> 		
  3774                              <1> ; / make a directory
  3775                              <1> 
  3776                              <1> 	;call	arg2
  3777                              <1> 	; * name - 'u.namep' points to address of file/path name
  3778                              <1> 	;          in the user's program segment ('u.segmnt')
  3779                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3780                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3781                              <1> 	;          which is on top of stack.
  3782                              <1> 
  3783                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3784                              <1> 			    ; / on stack
  3785 000037C7 891D[B0680000]      <1> 	mov	[u.namep], ebx
  3786                              <1> 	;push	cx ; mode
  3787                              <1> 	; 24/12/2021
  3788 000037CD 51                  <1> 	push	ecx ; cx = mode
  3789 000037CE E84C0A0000          <1> 	call	namei
  3790                              <1>         	; jsr r0,namei / get the i-number
  3791                              <1>         	;     br .+4 / if file not found branch around error
  3792                              <1>         ;xor 	ax, ax
  3793                              <1> 	;jnz	error
  3794 000037D3 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3795                              <1> 	;jnc	error	
  3796                              <1> 		; br  error2 / directory already exists (error)
  3797 000037D5 803D[E4680000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3798                              <1>         	;tstb u.uid / is user the super user
  3799                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3800                              <1> 	;;jna	error
  3801                              <1> 	; 26/02/2022 (BugFix)
  3802 000037DC 7721                <1> 	ja	short dir_access_err
  3803                              <1>         	;bne error2 / no, not allowed
  3804                              <1> 	;pop	ax
  3805                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3806                              <1> 	; 24/12/2021
  3807 000037DE 58                  <1> 	pop	eax  ; ax = mode
  3808 000037DF 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3809                              <1>         	;bic $!317,r1 / all but su and ex
  3810                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3811 000037E3 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3812                              <1>         	;bis $40000,r1 / directory flag
  3813 000037E6 E8400D0000          <1> 	call	maknod
  3814                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3815                              <1> ;sysclose_sysret: ; 26/02/2022
  3816 000037EB E942FBFFFF          <1> 	jmp	sysret
  3817                              <1>         	;br sysret2 /
  3818                              <1> dir_exists:
  3819                              <1> 	; 14/05/2015
  3820 000037F0 C705[ED680000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3820 000037F8 0000                <1>
  3821 000037FA E913FBFFFF          <1> 	jmp	error
  3822                              <1> dir_access_err:
  3823                              <1> 	; 14/05/2015
  3824 000037FF C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3824 00003807 0000                <1>
  3825 00003809 E904FBFFFF          <1> 	jmp	error
  3826                              <1> 
  3827                              <1> sysclose: ;<close file>
  3828                              <1> 	; 26/02/2022
  3829                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3830                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3831                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3832                              <1> 	;
  3833                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3834                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3835                              <1> 	; is put in r1 and 'fclose' is called.
  3836                              <1> 	;
  3837                              <1> 	; Calling sequence:
  3838                              <1> 	;	sysclose
  3839                              <1> 	; Arguments:
  3840                              <1> 	;	-  
  3841                              <1> 	; Inputs: *u.r0 - file descriptor
  3842                              <1> 	; Outputs: -
  3843                              <1> 	; ...............................................................
  3844                              <1> 	;				
  3845                              <1> 	; Retro UNIX 8086 v1 modification:
  3846                              <1> 	;	 The user/application program puts file descriptor
  3847                              <1> 	;        in BX register as 'sysclose' system call argument.
  3848                              <1> 	; 	 (argument transfer method 1)
  3849                              <1> 
  3850                              <1> 	; / close the file
  3851                              <1> 	
  3852 0000380E 89D8                <1> 	mov 	eax, ebx
  3853 00003810 E896090000          <1> 	call 	fclose
  3854                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3855                              <1> 		; jsr r0,fclose / close the file
  3856                              <1>                	; br error2 / unknown file descriptor
  3857                              <1> 		; br sysret2
  3858                              <1> 	; 14/05/2015
  3859                              <1> 	;jnc	sysret
  3860                              <1> 	; 04/12/2021
  3861 00003815 7205                <1> 	jc	short sysclose_err
  3862 00003817 E916FBFFFF          <1> 	jmp	sysret
  3863                              <1> 	; 26/02/2022
  3864                              <1> 	;jnc	short sysclose_sysret
  3865                              <1> sysclose_err:
  3866 0000381C C705[ED680000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3866 00003824 0000                <1>
  3867 00003826 E9E7FAFFFF          <1> 	jmp	error
  3868                              <1> 
  3869                              <1> sysemt:
  3870                              <1> 	; 26/02/2022
  3871                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3872                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3873                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3874                              <1> 	;
  3875                              <1> 	; Retro UNIX 8086 v1 modification: 
  3876                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3877                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3878                              <1> 	;
  3879                              <1> 	; Retro UNIX 8086 v1 feature only!
  3880                              <1> 	;	Using purpose: Kernel will start without time-out
  3881                              <1> 	;	(internal clock/timer) functionality.
  3882                              <1> 	;	Then etc/init will enable clock/timer for
  3883                              <1> 	;	multi tasking. (Then it will not be disabled again
  3884                              <1> 	;	except hardware reset/restart.)
  3885                              <1> 	;
  3886                              <1> 
  3887 0000382B 803D[E4680000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3888                              <1> 	;;ja	error
  3889                              <1> 	;ja	badsys ; 14/05/2015
  3890                              <1> 	; 24/12/2021
  3891 00003832 7605                <1> 	jna	short emt_0 
  3892 00003834 E98BFBFFFF          <1> 	jmp	badsys
  3893                              <1> emt_0:
  3894                              <1> 	; 24/12/2021
  3895                              <1> 	;cli
  3896 00003839 21DB                <1> 	and	ebx, ebx
  3897 0000383B 7429                <1> 	jz	short emt_2
  3898                              <1> 	; Enable multi tasking -time sharing-
  3899 0000383D B8[E4470000]        <1> 	mov	eax, clock
  3900                              <1> 	; 26/02/2022
  3901 00003842 BA[4B0A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3902                              <1> emt_1:
  3903 00003847 A3[10070000]        <1> 	mov	[x_timer], eax
  3904                              <1> 	; 26/02/2022 (Temporary)
  3905 0000384C 8915[14070000]      <1> 	mov	[x_rtci], edx
  3906 00003852 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3907 00003854 E851020000          <1> 	call	wttyc  ; clear video page
  3908 00003859 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3909 0000385B E84A020000          <1> 	call	wttyc  ; clear video page
  3910                              <1> 	;
  3911 00003860 FB                  <1> 	sti
  3912 00003861 E9CCFAFFFF          <1> 	jmp	sysret
  3913                              <1> emt_2:
  3914                              <1> 	; Disable multi tasking -time sharing-
  3915 00003866 B8[1C070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3916                              <1> 	; 26/02/2022
  3917 0000386B BA[520A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3918                              <1> 	;
  3919 00003870 EBD5                <1> 	jmp	short emt_1
  3920                              <1> 
  3921                              <1> 	; Original UNIX v1 'sysemt' routine
  3922                              <1> ;sysemt:
  3923                              <1>         ;
  3924                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3925                              <1> 			 ; / in loc 30
  3926                              <1>         ;cmp    30,$core / was the argument a lower address 
  3927                              <1> 			; / than core
  3928                              <1>         ;blo    1f / yes, rtssym
  3929                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3930                              <1> 			; / and less than "ecore"
  3931                              <1>         ;blo    2f / yes, sysret2
  3932                              <1> ;1:
  3933                              <1>         ;mov    $rtssym,30
  3934                              <1> ;2:
  3935                              <1>         ;br     sysret2
  3936                              <1> 
  3937                              <1> sysilgins:
  3938                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3939                              <1> 	; 03/06/2013
  3940                              <1> 	; Retro UNIX 8086 v1 modification: 
  3941                              <1> 	;	not a valid system call ! (not in use)
  3942                              <1> 	;
  3943 00003872 E94DFBFFFF          <1> 	jmp	badsys
  3944                              <1> 	;jmp	error
  3945                              <1> 	;;jmp 	sysret
  3946                              <1> 
  3947                              <1> 	; Original UNIX v1 'sysemt' routine
  3948                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3949                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3950                              <1> 			  ;/ put it in loc 8.,
  3951                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3952                              <1> 		       ; / trap address
  3953                              <1>         ;blo    1f / is the address a user core address?  
  3954                              <1> 		; / yes, go to 2f
  3955                              <1>         ;cmp    10,$ecore
  3956                              <1>         ;blo    2f
  3957                              <1> ;1:
  3958                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3959                              <1> 		    ; / instruction trap address for the system
  3960                              <1> ;2:
  3961                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3962                              <1> 
  3963                              <1> sysmdate: ; < change the modification time of a file >
  3964                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3965                              <1> 	;	(ECX input)
  3966                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3967                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3968                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3969                              <1> 	;
  3970                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3971                              <1> 	; file into core. The user is checked if he is the owner 
  3972                              <1> 	; or super user. If he is neither an error occurs.
  3973                              <1> 	; 'setimod' is then called to set the i-node modification
  3974                              <1> 	; byte and the modification time, but the modification time
  3975                              <1> 	; is overwritten by whatever get put on the stack during
  3976                              <1> 	; a 'systime' system call. This calls are restricted to
  3977                              <1> 	; the super user.		
  3978                              <1> 	;
  3979                              <1> 	; Calling sequence:
  3980                              <1> 	;	sysmdate; name
  3981                              <1> 	; Arguments:
  3982                              <1> 	;	name - points to the name of file
  3983                              <1> 	; Inputs: (arguments)
  3984                              <1> 	; Outputs: -
  3985                              <1> 	; ...............................................................
  3986                              <1> 	;				
  3987                              <1> 	; Retro UNIX 8086 v1 modification: 
  3988                              <1> 	;	 The user/application program puts address 
  3989                              <1> 	;	 of the file name in BX register 
  3990                              <1> 	;	 as 'sysmdate' system call argument.
  3991                              <1> 	;
  3992                              <1> ; / change the modification time of a file
  3993                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3994 00003877 891D[B0680000]      <1>         mov	[u.namep], ebx
  3995                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3996 0000387D 890D[20650000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3997 00003883 E897090000          <1> 	call	namei
  3998                              <1> 		; jsr r0,namei / get its i-number
  3999                              <1> 	;;jc	error       
  4000                              <1> 	;	; br error2 / no, such file
  4001                              <1> 	;jc	fnotfound ; file not found !
  4002                              <1> 	; 24/12/2021
  4003 00003888 7305                <1> 	jnc	short mdate_0
  4004 0000388A E99BFEFFFF          <1> 	jmp	fnotfound
  4005                              <1> mdate_0:
  4006 0000388F E89B110000          <1> 	call	iget
  4007                              <1> 		; jsr r0,iget / get i-node into core
  4008 00003894 A0[E4680000]        <1> 	mov	al, [u.uid]
  4009 00003899 3A05[97650000]      <1> 	cmp	al, [i.uid]
  4010                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  4011 0000389F 7413                <1> 	je	short mdate_1
  4012                              <1>         	; beq 1f / yes
  4013 000038A1 20C0                <1> 	and	al, al
  4014                              <1> 		; tstb u.uid / no, is user the super user
  4015                              <1> 	;jnz	error
  4016                              <1> 		; bne error2 / no, error
  4017 000038A3 740F                <1> 	jz	short mdate_1
  4018 000038A5 C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4018 000038AD 0000                <1>
  4019                              <1> sysstty_err:	; 04/02/2022
  4020 000038AF E95EFAFFFF          <1> 	jmp	error
  4021                              <1> mdate_1: ;1:
  4022 000038B4 E880120000          <1> 	call	setimod
  4023                              <1>         	; jsr r0,setimod / fill in modification data,
  4024                              <1> 		               ; / time etc.
  4025 000038B9 BE[20650000]        <1> 	mov	esi, p_time
  4026 000038BE BF[AE650000]        <1> 	mov	edi, i.mtim
  4027 000038C3 A5                  <1> 	movsd
  4028                              <1> 		; mov 4(sp),i.mtim / move present time to
  4029                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4030 000038C4 E969FAFFFF          <1>         jmp	sysret
  4031                              <1> 		; br sysret2
  4032                              <1> 
  4033                              <1> 	; 04/02/2022
  4034                              <1> sysstty_err_s:
  4035 000038C9 880D[98680000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4036 000038CF EBDE                <1> 	jmp	short sysstty_err
  4037                              <1> 
  4038                              <1> sysstty: ; < set tty status and mode >
  4039                              <1> 	; 26/02/2022
  4040                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4041                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4042                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4043                              <1> 	; 17/11/2015
  4044                              <1> 	; 12/11/2015
  4045                              <1> 	; 29/10/2015
  4046                              <1> 	; 17/10/2015
  4047                              <1> 	; 13/10/2015
  4048                              <1> 	; 29/06/2015
  4049                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4050                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4051                              <1> 	;
  4052                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4053                              <1> 	; whose file descriptor is in (u.r0).
  4054                              <1> 	;
  4055                              <1> 	; Calling sequence:
  4056                              <1> 	;	sysstty; arg
  4057                              <1> 	; Arguments:
  4058                              <1> 	;	arg - address of 3 consequitive words that contain
  4059                              <1> 	;	      the source of status data	
  4060                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4061                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4062                              <1> 	; ...............................................................
  4063                              <1> 	;	
  4064                              <1> 	; Retro UNIX 8086 v1 modification: 
  4065                              <1> 	;	'sysstty' system call will set the tty
  4066                              <1> 	;	(clear keyboard buffer and set cursor position)
  4067                              <1> 	;	 in following manner:
  4068                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4069                              <1> 	;
  4070                              <1> 	; Inputs:
  4071                              <1> 	;	BX = 0 --> means
  4072                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4073                              <1> 	;	      set cursor position for console tty, only 
  4074                              <1> 	;	      CH will be ignored (char. will not be written)	
  4075                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4076                              <1> 	;	      set console tty for (current) process
  4077                              <1> 	;	      CL = tty number (0 to 9)
  4078                              <1> 	;	      (If CH = 0, character will not be written)			
  4079                              <1> 	;          If CH > 0 (CL < FFh)	
  4080                              <1> 	;             CL = tty number (0 to 9)
  4081                              <1> 	;	      CH = character will be written
  4082                              <1> 	;	        at requested cursor position (in DX)	
  4083                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4084                              <1>   	;		(only tty number 0 to 7) 
  4085                              <1> 	;          DL = communication parameters (for serial ports) 
  4086                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4087                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4088                              <1> 	;			or set cursor position	
  4089                              <1> 	;	   DH = 0FFh -> DL is not valid
  4090                              <1> 	;		do not set serial port parameters 
  4091                              <1> 	;		or do not set cursor position
  4092                              <1> 	;
  4093                              <1> 	;	BX > 0 --> points to name of tty
  4094                              <1> 	;    	   CH > 0 -->
  4095                              <1> 	;		CH = character will be written in current 
  4096                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4097                              <1> 	;	     	or character will be sent to serial port
  4098                              <1> 	;	     	(for tty number 8 or 9)
  4099                              <1> 	;		CL = color of the character if tty number < 8.
  4100                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4101                              <1> 	;		set mode (tty 8 to 9) or 
  4102                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4103                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4104                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4105                              <1> 	;		(DL is not valid)
  4106                              <1> 	;	   DL = communication parameters 
  4107                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4108                              <1> 	;
  4109                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4110                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4111                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4112                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4113                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4114                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4115                              <1> 	;
  4116                              <1> 	; Outputs:
  4117                              <1> 	;	cf = 0 -> OK
  4118                              <1> 	;	     AL = tty number (0 to 9)
  4119                              <1> 	;	     AH = line status if tty number is 8 or 9
  4120                              <1> 	;	     AH = process number (of the caller) 	
  4121                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4122                              <1> 	;	     AH = FFh if the tty is locked 
  4123                              <1> 	;		  (owned by another process)
  4124                              <1> 	;	        = process number (of the caller) 
  4125                              <1> 	;		  (if < FFh and tty number < 8)
  4126                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4127                              <1> 	;	     AH = line status if tty number is 8 or 9
  4128                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4129                              <1> 	;	
  4130                              <1> 
  4131                              <1> 	; 27/06/2015 (32 bit modifications)
  4132                              <1> 	; 14/01/2014
  4133 000038D1 31C0                <1> 	xor 	eax, eax
  4134 000038D3 6648                <1> 	dec	ax ; 17/10/2015
  4135 000038D5 A3[98680000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4136                              <1> 	;;;
  4137                              <1> 	; 01/02/2022
  4138 000038DA FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4139 000038DC 39C2                <1> 	cmp	edx, eax
  4140                              <1> 	;cmp	dx, ax ; 0FFFFh
  4141 000038DE 7521                <1> 	jne	short sysstty_18
  4142                              <1> 	; clear video page
  4143                              <1> 	; (CH must be 0)
  4144 000038E0 08ED                <1> 	or	ch, ch
  4145 000038E2 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4146 000038E4 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4147 000038E7 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4148 000038E9 20C9                <1> 	and	cl, cl
  4149 000038EB 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4150 000038ED 0FB635[E7680000]    <1> 	movzx	esi, byte [u.uno]
  4151 000038F4 8A8E[F3650000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4152 000038FA 80F907              <1> 	cmp	cl, 7
  4153 000038FD 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4154                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4155 000038FF FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4156                              <1> sysstty_18:
  4157 00003901 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4158                              <1> 	; cl = video page (tty) number		
  4159                              <1> 	;;;
  4160 00003903 21DB                <1> 	and	ebx, ebx
  4161                              <1> 	;jnz	sysstty_6
  4162                              <1> 	; 01/02/2022
  4163 00003905 7405                <1> 	jz	short sysstty_19
  4164 00003907 E9C2000000          <1> 	jmp	sysstty_6
  4165                              <1> sysstty_19:
  4166                              <1> 	; set console tty
  4167                              <1> 	; 29/10/2015
  4168                              <1> 	; 17/01/2014 
  4169 0000390C 80F909              <1> 	cmp	cl, 9
  4170 0000390F 7613                <1> 	jna	short sysstty_0
  4171                              <1> 	; 17/11/2015
  4172 00003911 80F9FF              <1> 	cmp	cl, 0FFh
  4173 00003914 7202                <1> 	jb	short sysstty_13
  4174 00003916 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4175                              <1> sysstty_13:
  4176 00003918 8A1D[E7680000]      <1> 	mov	bl, [u.uno] ; process number
  4177 0000391E 8A8B[F3650000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4178                              <1> sysstty_0:
  4179                              <1> 	; 29/06/2015
  4180                              <1> 	;push	dx
  4181                              <1> 	;push	cx
  4182                              <1> 	; 01/02/2022
  4183 00003924 52                  <1> 	push	edx
  4184 00003925 51                  <1> 	push	ecx
  4185 00003926 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4186 00003928 88C8                <1> 	mov	al, cl
  4187 0000392A A2[98680000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4188 0000392F E8EF190000          <1> 	call	ottyp
  4189                              <1> 	; 01/02/2022
  4190 00003934 59                  <1> 	pop	ecx
  4191 00003935 5A                  <1> 	pop	edx
  4192                              <1> 	;pop	cx
  4193                              <1> 	;pop	dx
  4194                              <1> 	;
  4195 00003936 7220                <1> 	jc	short sysstty_pd_err
  4196                              <1> 	;
  4197                              <1> 	; 26/02/2022 (Bug! BugFix)
  4198                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4199                              <1> 	;
  4200 00003938 80F908              <1> 	cmp	cl, 8
  4201 0000393B 720C                <1> 	jb	short sysstty_2
  4202                              <1> 	;
  4203 0000393D 80FEFF              <1> 	cmp	dh, 0FFh
  4204 00003940 7407                <1> 	je	short sysstty_2
  4205                              <1> 		; set communication parameters for serial ports
  4206                              <1> 
  4207                              <1> ; 01/02/2022
  4208                              <1> ;	; 29/10/2015
  4209                              <1> ;	mov	ah, dl ; communication parameters
  4210                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4211                              <1> ;		;			 THRE int + RDA int 
  4212                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4213                              <1> ;		;			 THRE int + RDA int 
  4214                              <1> ;	sub	al, al ; 0
  4215                              <1> ;	; 12/07/2014
  4216                              <1> ;	cmp	cl, 9
  4217                              <1> ;	jb	short sysstty_1
  4218                              <1> ;	inc	al
  4219                              <1> ;sysstty_1:
  4220                              <1> ;	; 01/02/2022
  4221                              <1> ;	push	ecx
  4222                              <1> ;	;push	cx
  4223                              <1> ;	; 29/06/2015	
  4224                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4225                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4226                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4227                              <1> ;	; 01/02/2022
  4228                              <1> ;	pop	ecx	
  4229                              <1> ;	;pop	cx
  4230                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4231                              <1> 
  4232                              <1> 	; 01/02/2022
  4233 00003942 E830010000          <1> 	call	sysstty_scp
  4234 00003947 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4235                              <1> 
  4236                              <1> sysstty_2:
  4237                              <1> 	; 17/01/2014
  4238 00003949 20ED                <1> 	and	ch, ch 	; set cursor position 
  4239                              <1> 			; or comm. parameters ONLY
  4240 0000394B 7527                <1> 	jnz	short sysstty_3
  4241                              <1> 	; 01/02/2022
  4242 0000394D 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4243 00003951 7214                <1> 	jb	short sysstty_20
  4244                              <1> 	; clear screen (video page)
  4245 00003953 E93B010000          <1> 	jmp	sysstty_14
  4246                              <1> 
  4247                              <1> sysstty_pd_err: ; 29/06/2015
  4248                              <1> 	; 'permission denied !' error
  4249 00003958 C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4249 00003960 0000                <1>
  4250 00003962 E9ABF9FFFF          <1> 	jmp	error
  4251                              <1> 
  4252                              <1> sysstty_20:
  4253 00003967 0FB61D[E7680000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4254 0000396E 888B[F3650000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4255                              <1> sysstty_3:
  4256                              <1> 	; 16/01/2014
  4257 00003974 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4258                              <1> 	; 17/11/2015
  4259 00003976 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4260 00003978 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4261                              <1> 	;jna	sysstty_9
  4262                              <1> 	; 01/02/2022
  4263 0000397A 7705                <1> 	ja	short sysstty_12
  4264 0000397C E9C5000000          <1> 	jmp	sysstty_9
  4265                              <1> 
  4266                              <1> sysstty_12:
  4267                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4268                              <1> 	; (Set specified serial port as console tty port)
  4269                              <1> 	; CH = character to be written
  4270                              <1> 	; 15/04/2014
  4271                              <1> 	; CH = 0 --> initialization only
  4272                              <1> 	; AL = character
  4273                              <1> 	; 26/06/2014
  4274 00003981 880D[EC680000]      <1> 	mov	[u.ttyn], cl
  4275                              <1> 	; 12/07/2014
  4276 00003987 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4277                              <1> 	; 02/02/2022
  4278 00003989 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4279 0000398B 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4280 0000398D FEC8                <1> 	dec	al  ; 1 -> 0	
  4281                              <1> 	;and	al, al
  4282 0000398F 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4283                              <1>  	; 04/07/2014
  4284 00003991 E8E71F0000          <1> 	call 	sndc
  4285                              <1> 	; 12/07/2014
  4286 00003996 EB0C                <1> 	jmp	short sysstty_5
  4287                              <1> 
  4288                              <1> sysstty_4:
  4289                              <1> 	; 12/07/2014
  4290                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4291 00003998 88E0                <1> 	mov	al, ah ; 29/06/2015
  4292 0000399A 2C08                <1> 	sub	al, 8
  4293                              <1> 	; 27/06/2015
  4294 0000399C E824F4FFFF          <1> 	call	sp_status ; get serial port status
  4295                              <1> 	; AL = Line status, AH = Modem status
  4296                              <1> 	; 12/11/2015
  4297 000039A1 3C80                <1> 	cmp	al, 80h
  4298 000039A3 F5                  <1> 	cmc
  4299                              <1> sysstty_5:
  4300 000039A4 66A3[99680000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4301                              <1> 		; EAX bits 16-23 = modem status	
  4302 000039AA 9C                  <1> 	pushf
  4303 000039AB 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4304 000039AD A0[EC680000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4305 000039B2 E88F1A0000          <1> 	call	cttyp
  4306 000039B7 9D                  <1> 	popf
  4307                              <1> 	;jnc	sysret ; time out error 
  4308                              <1> 	; 01/02/2022
  4309 000039B8 7205                <1> 	jc	short sysstty_tmout_err
  4310 000039BA E973F9FFFF          <1> 	jmp	sysret
  4311                              <1> 
  4312                              <1> sysstty_tmout_err:
  4313 000039BF C705[ED680000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4313 000039C7 0000                <1>
  4314 000039C9 E944F9FFFF          <1> 	jmp	error
  4315                              <1> 
  4316                              <1> sysstty_6:
  4317                              <1> 	;push	dx
  4318                              <1> 	;push	cx
  4319                              <1> 	; 01/02/2022
  4320 000039CE 52                  <1> 	push	edx
  4321 000039CF 51                  <1> 	push	ecx
  4322 000039D0 891D[B0680000]      <1> 	mov	[u.namep], ebx
  4323 000039D6 E844080000          <1> 	call	namei
  4324                              <1> 	; 01/02/2022
  4325 000039DB 59                  <1> 	pop	ecx
  4326 000039DC 5A                  <1> 	pop	edx
  4327                              <1> 	;pop	cx
  4328                              <1> 	;pop	dx
  4329 000039DD 7258                <1> 	jc	short sysstty_inv_dn
  4330                              <1> 	;
  4331 000039DF 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4332 000039E3 7752                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4333                              <1> 	;
  4334 000039E5 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4335                              <1> 		       ; /dev/COM1, /dev/COM2
  4336 000039E7 7204                <1> 	jb	short sysstty_7
  4337 000039E9 2C0A                <1> 	sub	al, 10
  4338 000039EB EB11                <1> 	jmp	short sysstty_8
  4339                              <1> 
  4340                              <1> sysstty_7:
  4341 000039ED 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4342 000039EF 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4343 000039F1 0FB61D[E7680000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4344 000039F8 8A83[F3650000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4345                              <1> sysstty_8:
  4346                              <1> 	; 26/02/2022
  4347                              <1> 	; (ebx < 256)	
  4348 000039FE A2[98680000]        <1> 	mov	[u.r0], al
  4349                              <1> 	; 01/02/2022
  4350                              <1> 	;push	dx
  4351                              <1> 	;push	ax
  4352                              <1> 	;push	cx
  4353 00003A03 52                  <1> 	push	edx
  4354 00003A04 50                  <1> 	push	eax
  4355 00003A05 51                  <1> 	push	ecx	
  4356 00003A06 E818190000          <1> 	call	ottyp
  4357 00003A0B 59                  <1> 	pop	ecx
  4358 00003A0C 58                  <1> 	pop	eax
  4359 00003A0D 5A                  <1> 	pop	edx
  4360                              <1> 	;pop	cx
  4361                              <1> 	;pop	ax
  4362                              <1> 	;pop	dx
  4363                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4364                              <1> 	; 01/02/2022
  4365 00003A0E 7305                <1> 	jnc	short sysstty_21
  4366 00003A10 E943FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4367                              <1> sysstty_21:
  4368                              <1> 	; 29/10/2015
  4369 00003A15 86E9                <1> 	xchg 	ch, cl
  4370                              <1> 		; cl = character, ch = color code
  4371 00003A17 86C1                <1> 	xchg	al, cl
  4372                              <1> 		; al = character, cl = tty number
  4373 00003A19 80F907              <1> 	cmp	cl, 7
  4374                              <1> 	;ja	sysstty_12
  4375                              <1> 	; 01/02/2022
  4376 00003A1C 7628                <1> 	jna	short sysstty_16
  4377                              <1> ;;
  4378 00003A1E 80FEFF              <1> 	cmp	dh, 0FFh
  4379 00003A21 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4380                              <1> 
  4381                              <1> ; 01/02/2022
  4382                              <1> ;	; 29/10/2015
  4383                              <1> ;	mov	ah, dl ; communication parameters
  4384                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4385                              <1> ;		;			 THRE int + RDA int 
  4386                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4387                              <1> ;		;			 THRE int + RDA int 
  4388                              <1> ;	sub	al, al ; 0
  4389                              <1> ;	; 12/07/2014
  4390                              <1> ;	cmp	cl, 9
  4391                              <1> ;	jb	short sysstty_1
  4392                              <1> ;	inc	al
  4393                              <1> ;sysstty_1:
  4394                              <1> ;	; 01/02/2022
  4395                              <1> ;	push	ecx
  4396                              <1> ;	;push	cx
  4397                              <1> ;	; 29/06/2015	
  4398                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4399                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4400                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4401                              <1> ;	; 01/02/2022
  4402                              <1> ;	pop	ecx	
  4403                              <1> ;	;pop	cx
  4404                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4405                              <1> 
  4406                              <1> 	; 02/02/2022
  4407 00003A23 88C5                <1> 	mov	ch, al ; save char
  4408                              <1> 	; 01/02/2022
  4409 00003A25 E84D000000          <1> 	call	sysstty_scp
  4410 00003A2A 7293                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4411                              <1> 	; 02/02/2022
  4412 00003A2C 88E8                <1> 	mov	al, ch ; restore char
  4413                              <1> sysstty_22:
  4414                              <1> 	; 01/02/2022
  4415 00003A2E 08ED                <1> 	or	ch, ch
  4416 00003A30 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4417                              <1> 	; send char to (serial port) terminal
  4418                              <1> 	; al = character
  4419                              <1> 	; cl = tty number (8 or 9)
  4420 00003A32 E94AFFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4421                              <1> 
  4422                              <1> sysstty_inv_dn: 
  4423                              <1> 	; 27/06/2015
  4424                              <1> 	; Invalid device name (not a tty) ! error
  4425                              <1> 	; (Device is not a tty or device name not found)
  4426 00003A37 C705[ED680000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4426 00003A3F 0000                <1>
  4427 00003A41 E9CCF8FFFF          <1> 	jmp	error 
  4428                              <1> 
  4429                              <1> sysstty_16:
  4430                              <1> 	; 26/02/2022
  4431                              <1> 	; 16/01/2014
  4432                              <1> 	;xor	bh, bh
  4433                              <1> 	; 02/02/2022
  4434                              <1> sysstty_9: 	; tty 0 to tty 7
  4435                              <1> 	; al = character
  4436                              <1> 	; ch = color/attribute ; 01/02/2022
  4437                              <1> 	;
  4438                              <1> 	; 26/02/2022 (BugFix)
  4439                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4440 00003A46 29DB                <1> 	sub	ebx, ebx ; *
  4441 00003A48 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4442 00003A4B 740B                <1> 	je	short sysstty_10
  4443                              <1> 	; 02/02/2022
  4444 00003A4D 51                  <1> 	push	ecx
  4445 00003A4E 50                  <1> 	push	eax
  4446                              <1> 	;push	cx
  4447                              <1> 	;push	ax	
  4448                              <1> 	;movzx	ebx, cl
  4449 00003A4F 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4450 00003A51 E875DAFFFF          <1> 	call	set_cpos
  4451                              <1> 	;pop	ax
  4452                              <1> 	;pop	cx
  4453                              <1> 	; 02/02/2022
  4454 00003A56 58                  <1> 	pop	eax
  4455 00003A57 59                  <1> 	pop	ecx
  4456                              <1> sysstty_10: 
  4457                              <1> 	; 29/10/2015
  4458 00003A58 08C0                <1> 	or	al, al ; character
  4459 00003A5A 740D                <1> 	jz      short sysstty_11 ; al = 0
  4460                              <1> 	; 17/11/2015
  4461 00003A5C 3CFF                <1> 	cmp	al, 0FFh
  4462 00003A5E 7309                <1> 	jnb	short sysstty_11
  4463                              <1> 		; ch > 0 and ch < FFh
  4464                              <1> 	; write a character at current cursor position
  4465 00003A60 88EC                <1> 	mov	ah, ch ; color/attribute
  4466                              <1> 	; 12/07/2014
  4467                              <1> 	;push	cx
  4468                              <1> 	; 02/02/2022
  4469 00003A62 51                  <1> 	push	ecx
  4470 00003A63 E84BDBFFFF          <1> 	call	write_c_current
  4471                              <1> 	;pop	cx
  4472                              <1> 	; 02/02/2022
  4473 00003A68 59                  <1> 	pop	ecx
  4474                              <1> sysstty_11:
  4475                              <1> 	; 14/01/2014
  4476 00003A69 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4477                              <1> 	; 18/01/2014
  4478                              <1> 	;movzx	eax, cl ; 27/06/2015
  4479 00003A6B 88C8                <1> 	mov	al, cl
  4480 00003A6D E8D4190000          <1> 	call	cttyp
  4481 00003A72 E9BBF8FFFF          <1> 	jmp	sysret
  4482                              <1> 
  4483                              <1> sysstty_scp:
  4484                              <1> 	; 02/02/2022
  4485                              <1> 	; set communication parameters (for COM1 or COM2)
  4486                              <1> 	; 01/02/2022
  4487                              <1> 	;
  4488                              <1> 	; 29/10/2015
  4489 00003A77 88D4                <1> 	mov	ah, dl ; communication parameters
  4490                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4491                              <1> 		;			 THRE int + RDA int 
  4492                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4493                              <1> 		;			 THRE int + RDA int 
  4494 00003A79 28C0                <1> 	sub	al, al ; 0
  4495                              <1> 	; 12/07/2014
  4496 00003A7B 80F909              <1> 	cmp	cl, 9
  4497 00003A7E 7202                <1> 	jb	short sysstty_1
  4498 00003A80 FEC0                <1> 	inc	al
  4499                              <1> sysstty_1:
  4500                              <1> 	; 02/02/2022
  4501 00003A82 52                  <1> 	push	edx
  4502                              <1> 	; 01/02/2022
  4503 00003A83 51                  <1> 	push	ecx
  4504                              <1> 	;push	cx
  4505                              <1> 	; 29/06/2015	
  4506 00003A84 E844F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4507 00003A89 66890D[99680000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4508                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4509                              <1> 	; 01/02/2022
  4510 00003A90 59                  <1> 	pop	ecx	
  4511                              <1> 	;pop	cx
  4512 00003A91 5A                  <1> 	pop	edx ; 02/02/2022
  4513                              <1> 	; 01/02/2022
  4514                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4515 00003A92 C3                  <1> 	retn
  4516                              <1> 
  4517                              <1> sysstty_14:
  4518                              <1> 	; 26/02/2022
  4519                              <1> 	; 02/02/2022
  4520                              <1> 	; ch = 0
  4521                              <1> 	; cl = video page
  4522                              <1> 	;
  4523                              <1> 	; dx = 0FFFFh
  4524                              <1> 	; clear screen (video page)
  4525                              <1> 	;
  4526                              <1> 
  4527                              <1> 	; 02/02/2022
  4528                              <1> 	; clear screen
  4529                              <1> 	;
  4530                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4531                              <1> 	; clear video page
  4532                              <1> 
  4533                              <1> 	; 26/02/2022
  4534 00003A93 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4535                              <1> 
  4536                              <1> 	; clear video page
  4537 00003A95 E810000000          <1> 	call	wttyc ; 26/02/2022
  4538                              <1> 
  4539                              <1> 	; 26/02/2022
  4540 00003A9A 88D8                <1> 	mov	al, bl
  4541 00003A9C 8A25[E7680000]      <1> 	mov	ah, [u.uno]
  4542 00003AA2 66A3[98680000]      <1> 	mov	[u.r0], ax
  4543 00003AA8 EBBF                <1> 	jmp	short sysstty_11
  4544                              <1> 
  4545                              <1> vp_clr:	; 27/02/2022
  4546                              <1> wttyc:
  4547                              <1> 	; 23/02/2022
  4548                              <1> 	; (clear video page)
  4549                              <1> 	; INPUT:
  4550                              <1> 	;  bl = video page (0 to 7)
  4551                              <1> 	;
  4552                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4553                              <1> 
  4554                              <1> 	;xor	dx, dx ; column 0, row 0
  4555                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4556                              <1> 	;
  4557                              <1> ;	movzx	ebx, cl
  4558                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4559                              <1> 
  4560                              <1> ;	shl 	bl, 1 
  4561                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4562                              <1> ;		; AL = lock value (0 or process number)
  4563                              <1> ;	or	al, al
  4564                              <1> ;	jz	short @f
  4565                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4566                              <1> ;	jne	short sysstty_15
  4567                              <1> ;		; only the owner can clear its video page
  4568                              <1> ;	xor	al, al ; 0
  4569                              <1> ;@@:
  4570                              <1> ;	;mov	bl, cl		
  4571                              <1> ;	shr	bl, 1 
  4572                              <1> 
  4573 00003AAA 30C0                <1> 	xor	al, al	; 0
  4574 00003AAC B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4575                              <1> 
  4576                              <1> 	; scroll_up input:
  4577                              <1> 	;
  4578                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4579                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4580                              <1> 	; ah = attribute to be used on blanked line
  4581                              <1> 	; bl = video page number (0 to 7)
  4582                              <1> 
  4583 00003AAE E89EDAFFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4584                              <1> 
  4585                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4586                              <1> 
  4587                              <1> 	; bl = video page number (0 to 7)
  4588                              <1> 	;xor	dx, dx ; column 0, row 0
  4589                              <1> 	; 02/02/2022
  4590 00003AB3 31D2                <1> 	xor	edx, edx
  4591                              <1> 	; 26/02/2022
  4592                              <1> 	;call	set_cpos
  4593                              <1> 	;retn
  4594 00003AB5 E911DAFFFF          <1> 	jmp	set_cpos
  4595                              <1> 
  4596                              <1> 	;mov	al, bl
  4597                              <1> 	;mov	ah, [u.uno]
  4598                              <1> 	;mov	[u.r0], ax
  4599                              <1> 	;jmp	short sysstty_11
  4600                              <1> 
  4601                              <1> ;sysstty_15:
  4602                              <1> ;	; 30/01/2022
  4603                              <1> ;	; permission (denied) error
  4604                              <1> ;	;xor	dl, dl ; sysstty call sign
  4605                              <1> ;	mov	al, cl
  4606                              <1> ;	sub	ah, ah ; 0
  4607                              <1> ;	call	cttyp
  4608                              <1> ;	jmp	error
  4609                              <1> 
  4610                              <1> ; Original UNIX v1 'sysstty' routine:
  4611                              <1> ; gtty:
  4612                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4613                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4614                              <1> 	; 		/ r2 has source
  4615                              <1>         ;mov    r2,-(sp)
  4616                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4617                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4618                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4619                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4620                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4621                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4622                              <1>         ;       br .+4 / list empty, skip branch
  4623                              <1>         ;br     1b / get another character until list is empty
  4624                              <1>         ;mov    0b,r1 / move cc offset to r1
  4625                              <1>         ;inc    r1 / bump it for output clist
  4626                              <1>         ;tstb   cc(r1) / is it 0
  4627                              <1>         ;beq    1f / yes, no characters to output
  4628                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4629                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4630                              <1>         ;br     1b / try to calm it down again
  4631                              <1> ;1:
  4632                              <1>         ;mov    (sp)+,r1
  4633                              <1>         ;mov    (sp)+,r2 / restore registers
  4634                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4635                              <1>         ;beq    1f / if 0, 1f
  4636                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4637                              <1>         ;                   / control status register
  4638                              <1> ;1:
  4639                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4640                              <1>         ;beq    1f / if 0 1f
  4641                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4642                              <1> 	;		    / control status reg
  4643                              <1> ;1:
  4644                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4645                              <1>         ;jmp     sysret2 / return to user
  4646                              <1> 
  4647                              <1> sysgtty: ; < get tty status >
  4648                              <1> 	; 26/02/2022
  4649                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4650                              <1> 	;	    ((32 bit reg push/pop))
  4651                              <1> 	; 23/11/2015
  4652                              <1> 	; 29/10/2015
  4653                              <1> 	; 17/10/2015
  4654                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4655                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4656                              <1> 	;
  4657                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4658                              <1> 	; It stores in the three words addressed by it's argument
  4659                              <1> 	; the status of the typewriter whose file descriptor
  4660                              <1> 	; in (u.r0).
  4661                              <1> 	;
  4662                              <1> 	; Calling sequence:
  4663                              <1> 	;	sysgtty; arg
  4664                              <1> 	; Arguments:
  4665                              <1> 	;	arg - address of 3 words destination of the status
  4666                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4667                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4668                              <1> 	; ...............................................................
  4669                              <1> 	;	
  4670                              <1> 	; Retro UNIX 8086 v1 modification: 
  4671                              <1> 	;	'sysgtty' system call will return status of tty
  4672                              <1> 	;	(keyboard, serial port and video page status)
  4673                              <1> 	;	 in following manner:
  4674                              <1> 	;
  4675                              <1> 	; Inputs:
  4676                              <1> 	;	BX = 0 --> means 
  4677                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4678                              <1> 	;	                 for (current) process
  4679                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4680                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4681                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4682                              <1> 	;	     CH > 0 -->	tty number + 1
  4683                              <1> 	;
  4684                              <1> 	;	BX > 0 --> points to name of tty
  4685                              <1> 	;	     CL = 0 --> return keyboard status
  4686                              <1> 	;	     CL = 1 --> return video page status
  4687                              <1> 	;	     CH = undefined		 
  4688                              <1> 	;
  4689                              <1> 	; Outputs:
  4690                              <1> 	;	cf = 0 ->
  4691                              <1> 	;
  4692                              <1> 	;	     AL = tty number from 0 to 9
  4693                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4694                              <1> 	;	     AH = 0 if the tty is free/unused
  4695                              <1> 	;	     AH = the process number of the caller 
  4696                              <1>  	;	     AH = FFh if the tty is locked by another process
  4697                              <1> 	;
  4698                              <1> 	;	  (if calling is for serial port status)
  4699                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4700                              <1> 	;		  (BH = modem status, BL = Line status)
  4701                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4702                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4703                              <1> 	;
  4704                              <1> 	;	  (if calling is for keyboard status)
  4705                              <1> 	;	     BX = current character in tty/keyboard buffer
  4706                              <1> 	;		  (BH = scan code, BL = ascii code)
  4707                              <1> 	;		  (BX=0 if there is not a waiting character)
  4708                              <1> 	;	     CX  is undefined
  4709                              <1> 	;
  4710                              <1> 	;	  (if calling is for video page status)	
  4711                              <1> 	;	     BX = cursor position on the video page
  4712                              <1> 	;		  if tty number < 8
  4713                              <1> 	;		  (BH = row, BL = column)
  4714                              <1> 	;	     CX = current character (in cursor position)
  4715                              <1> 	;		  on the video page of the tty 
  4716                              <1> 	;		  if tty number < 8
  4717                              <1> 	;		  (CH = color, CL = character)
  4718                              <1> 	;	
  4719                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4720                              <1> 	;
  4721                              <1> 	;	     AH = FFh if the caller is not owner of
  4722                              <1> 	;		  specified tty or console tty
  4723                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4724                              <1> 	;	     BX, CX are undefined if cf = 1
  4725                              <1> 	;
  4726                              <1> 	;	  (If tty number is 8 or 9)
  4727                              <1> 	;	     AL = tty number 
  4728                              <1> 	;	     AH = the process number of the caller 
  4729                              <1> 	;	     BX = serial port status
  4730                              <1> 	;  		 (BH = modem status, BL = Line status)
  4731                              <1> 	;	     CX = 0
  4732                              <1> 	;
  4733                              <1> 		
  4734                              <1> gtty:   ; get (requested) tty number
  4735                              <1> 	; 26/02/2022
  4736                              <1> 	; 17/10/2015
  4737                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4738                              <1> 	; 30/05/2013 - 12/07/2014
  4739                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4740                              <1> 	;
  4741                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4742                              <1> 	;
  4743                              <1> 	; 28/06/2015 (32 bit modifications)
  4744                              <1> 	; 16/01/2014
  4745 00003ABA 31C0                <1> 	xor 	eax, eax
  4746 00003ABC 6648                <1> 	dec	ax ; 17/10/2015
  4747 00003ABE A3[98680000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4748 00003AC3 80F901              <1> 	cmp	cl, 1
  4749 00003AC6 760F                <1> 	jna	short sysgtty_0
  4750                              <1> sysgtty_invp:
  4751                              <1> 	; 28/06/2015
  4752 00003AC8 C705[ED680000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4752 00003AD0 0000                <1>
  4753 00003AD2 E93BF8FFFF          <1> 	jmp	error
  4754                              <1> sysgtty_0:	
  4755 00003AD7 21DB                <1> 	and	ebx, ebx
  4756 00003AD9 742E                <1> 	jz	short sysgtty_1
  4757                              <1> 	;
  4758 00003ADB 891D[B0680000]      <1> 	mov	[u.namep], ebx
  4759                              <1> 	;push	cx ; 23/11/2015
  4760 00003AE1 51                  <1> 	push	ecx ; 24/12/2021
  4761 00003AE2 E838070000          <1> 	call	namei
  4762 00003AE7 59                  <1> 	pop	ecx
  4763                              <1> 	;pop	cx ; 23/11/2015
  4764 00003AE8 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4765                              <1> 	;
  4766 00003AEA 6683F801            <1> 	cmp	ax, 1
  4767 00003AEE 7622                <1> 	jna	short sysgtty_2
  4768                              <1> 	; 26/02/2022
  4769 00003AF0 20E4                <1> 	and	ah, ah
  4770 00003AF2 7506                <1> 	jnz	short sysgtty_inv_dn
  4771                              <1> 	;sub	ax, 10
  4772 00003AF4 2C0A                <1> 	sub	al, 10
  4773 00003AF6 3C09                <1> 	cmp	al, 9
  4774                              <1> 	;cmp	ax, 9
  4775                              <1> 	;ja	short sysgtty_inv_dn
  4776                              <1> 	;mov	ch, al
  4777                              <1> 	;jmp	short sysgtty_4
  4778                              <1> 	; 23/11/2015
  4779 00003AF8 7629                <1> 	jna	short sysgtty_4
  4780                              <1> sysgtty_inv_dn: 
  4781                              <1> 	; 28/06/2015
  4782                              <1> 	; Invalid device name (not a tty) ! error
  4783                              <1> 	; (Device is not a tty or device name not found)
  4784 00003AFA C705[ED680000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4784 00003B02 0000                <1>
  4785 00003B04 E909F8FFFF          <1> 	jmp	error 
  4786                              <1> sysgtty_1:
  4787                              <1> 	; 16/01/2014
  4788 00003B09 80FD0A              <1> 	cmp	ch, 10
  4789 00003B0C 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4790 00003B0E FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4791 00003B10 790F                <1> 	jns	short sysgtty_3 ; not negative
  4792                              <1> 	;
  4793                              <1> sysgtty_2:
  4794                              <1> 	; get tty number of console tty
  4795 00003B12 8A25[E7680000]      <1> 	mov	ah, [u.uno]
  4796                              <1>  	; 28/06/2015
  4797 00003B18 0FB6DC              <1> 	movzx 	ebx, ah
  4798 00003B1B 8AAB[F3650000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4799                              <1> sysgtty_3:
  4800 00003B21 88E8                <1> 	mov	al, ch
  4801                              <1> sysgtty_4:
  4802 00003B23 A2[98680000]        <1> 	mov	[u.r0], al
  4803                              <1>  	; 28/06/2015
  4804                              <1> 	;cmp	al, 9
  4805                              <1> 	;ja	short sysgtty_invp
  4806 00003B28 8B2D[94680000]      <1> 	mov	ebp, [u.usp]
  4807                              <1> 	; 23/11/2015
  4808 00003B2E 20C9                <1> 	and	cl, cl
  4809 00003B30 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4810 00003B32 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4811 00003B34 722E                <1> 	jb	short sysgtty_6 ; video page status
  4812                              <1> 	; serial port status
  4813                              <1> 	; 12/07/2014
  4814                              <1> 	;mov	dx, 0
  4815                              <1> 	;je	short sysgtty_5
  4816                              <1> 	;inc	dl
  4817                              <1> ;sysgtty_5:
  4818                              <1> 	; 28/06/2015
  4819 00003B36 2C08                <1> 	sub	al, 8
  4820 00003B38 E888F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4821                              <1> 	; AL = Line status, AH = Modem status
  4822 00003B3D 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4823 00003B41 8A25[E7680000]      <1> 	mov	ah, [u.uno]
  4824 00003B47 8825[99680000]      <1>         mov     [u.r0+1], ah
  4825                              <1> 	; 24/12/2021
  4826 00003B4D 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4827                              <1> 				; (in ECX)
  4828 00003B53 A880                <1> 	test	al, 80h
  4829 00003B55 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4830 00003B57 A801                <1> 	test	al, 1
  4831                              <1> 	;jz	sysret
  4832 00003B59 7404                <1> 	jz	short sysgtty_10
  4833 00003B5B 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4834                              <1> sysgtty_10:
  4835 00003B5F E9CEF7FFFF          <1> 	jmp	sysret
  4836                              <1> sysgtty_6:
  4837 00003B64 A2[EC680000]        <1> 	mov	[u.ttyn], al ; tty number
  4838                              <1> 	;movzx	ebx, al
  4839 00003B69 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4840 00003B6B D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4841                              <1> 	; 22/04/2014 - 29/06/2015
  4842 00003B6D 81C3[24650000]      <1>         add     ebx, ttyl
  4843 00003B73 8A23                <1>  	mov	ah, [ebx]
  4844 00003B75 3A25[E7680000]      <1> 	cmp	ah, [u.uno]
  4845 00003B7B 7404                <1> 	je	short sysgtty_7
  4846 00003B7D 20E4                <1> 	and	ah, ah
  4847                              <1> 	;jz	short sysgtty_7
  4848 00003B7F 7506                <1> 	jnz	short sysgtty_8
  4849                              <1> 	;mov	ah, 0FFh
  4850                              <1> sysgtty_7:
  4851 00003B81 8825[99680000]      <1>         mov     [u.r0+1], ah
  4852                              <1> sysgtty_8:
  4853 00003B87 08C9                <1> 	or	cl, cl
  4854 00003B89 7510                <1> 	jnz	short sysgtty_9
  4855 00003B8B B001                <1> 	mov	al, 1  ; test a key is available
  4856 00003B8D E86E1D0000          <1> 	call	getc
  4857 00003B92 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4858 00003B96 E997F7FFFF          <1> 	jmp	sysret
  4859                              <1> sysgtty_9:
  4860 00003B9B 8A1D[EC680000]      <1> 	mov	bl, [u.ttyn]
  4861                              <1> 	; bl = video page number
  4862 00003BA1 E8CB1E0000          <1> 	call 	get_cpos
  4863                              <1> 	; dx = cursor position
  4864 00003BA6 66895510            <1> 	mov	[ebp+16], dx ; bx
  4865                              <1> 	;mov	bl, [u.ttyn]
  4866                              <1> 	; bl = video page number
  4867 00003BAA E8D31E0000          <1> 	call	read_ac_current
  4868                              <1> 	; ax = character and attribute/color
  4869 00003BAF 66894518            <1> 	mov	[ebp+24], ax ; cx
  4870 00003BB3 E97AF7FFFF          <1> 	jmp	sysret
  4871                              <1> sysgtty_dnr_err:
  4872                              <1> 	; 'device not responding !' error	
  4873                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4874 00003BB8 C705[ED680000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4874 00003BC0 0000                <1>
  4875 00003BC2 E94BF7FFFF          <1> 	jmp	error	
  4876                              <1> 
  4877                              <1> ; Original UNIX v1 'sysgtty' routine:
  4878                              <1> ; sysgtty:
  4879                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4880                              <1> 	;	       / r2 has destination
  4881                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4882                              <1> 	;                     / in 1st word of dest
  4883                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4884                              <1> 	;                     / in 2nd word of dest
  4885                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4886                              <1>         ;jmp    sysret2 / return to user
  4887                              <1> 	
  4888                              <1> ; Original UNIX v1 'gtty' routine:
  4889                              <1> ; gtty:
  4890                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4891                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4892                              <1>         ;jsr    r0,getf / get the i-number of the file
  4893                              <1>         ;tst    r1 / is it open for reading
  4894                              <1>         ;bgt    1f / yes
  4895                              <1>         ;neg    r1 / no, i-number is negative, 
  4896                              <1> 	;          / so make it positive
  4897                              <1> ;1:
  4898                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4899                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4900                              <1>         ;bhis   error9 / no, error
  4901                              <1>         ;asl    r1 / 0%2
  4902                              <1>         ;asl    r1 / 0%4 / yes
  4903                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4904                              <1> 	;	       ; / tty block
  4905                              <1>         ;mov    u.off,r2 / put argument in r2
  4906                              <1>         ;rts    r0 / return
  2106                                  %include 'u2.s'        ; 11/05/2015
  2107                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS2.INC
  2108                              <1> ; Last Modification: 15/05/2022
  2109                              <1> ; ----------------------------------------------------------------------------
  2110                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2111                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2112                              <1> ;
  2113                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2114                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2115                              <1> ; <Bell Laboratories (17/3/1972)>
  2116                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2117                              <1> ;
  2118                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2119                              <1> ;
  2120                              <1> ; ****************************************************************************
  2121                              <1> 
  2122                              <1> syslink:
  2123                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2124                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2125                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2126                              <1> 	;
  2127                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2128                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2129                              <1> 	; given to the entry that will go in the current directory.
  2130                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2131                              <1> 	; in the name 2 entry of current directory is the same
  2132                              <1> 	; i-number for the name 1 file.
  2133                              <1> 	;
  2134                              <1> 	; Calling sequence:
  2135                              <1> 	;	syslink; name 1; name 2
  2136                              <1> 	; Arguments:
  2137                              <1> 	;	name 1 - file name to which link will be created.
  2138                              <1> 	;	name 2 - name of entry in current directory that
  2139                              <1> 	;		 links to name 1.
  2140                              <1> 	; Inputs: -
  2141                              <1> 	; Outputs: -
  2142                              <1> 	; ...............................................................
  2143                              <1> 	;	
  2144                              <1> 	; Retro UNIX 8086 v1 modification: 
  2145                              <1> 	;       'syslink' system call has two arguments; so,
  2146                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2147                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2148                              <1> 	;
  2149                              <1> 		; / name1, name2
  2150                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2151 00003BC7 891D[B0680000]      <1> 	mov	[u.namep], ebx
  2152 00003BCD 51                  <1> 	push	ecx
  2153 00003BCE E84C060000          <1> 	call	namei
  2154                              <1> 		; jsr r0,namei / find the i-number associated with
  2155                              <1> 			     ; / the 1st path name
  2156                              <1>      	;;and	ax, ax
  2157                              <1> 	;;jz	error ; File not found
  2158                              <1> 	;jc	error 
  2159                              <1> 		; br error9 / cannot be found
  2160 00003BD3 730F                <1> 	jnc	short syslink0
  2161                              <1> 	;pop 	ecx
  2162                              <1> 	; 'file not found !' error
  2163 00003BD5 C705[ED680000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2163 00003BDD 0000                <1>
  2164 00003BDF E92EF7FFFF          <1> 	jmp	error
  2165                              <1> syslink0:
  2166 00003BE4 E8460E0000          <1> 	call	iget
  2167                              <1> 		; jsr r0,iget / get the i-node into core
  2168 00003BE9 8F05[B0680000]      <1> 	pop	dword [u.namep] ; ecx
  2169                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2170                              <1> 	; 24/12/2021
  2171 00003BEF 50                  <1> 	push	eax ; *
  2172                              <1> 	;push	ax
  2173                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2174                              <1> 			    ; / (a link to this file is to be created)
  2175                              <1> 	; 24/12/2021
  2176 00003BF0 8A0D[7B680000]      <1> 	mov	cl, [cdev]
  2177 00003BF6 51                  <1> 	push	ecx ; **
  2178                              <1> 	;push	word [cdev]
  2179                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2180 00003BF7 E852000000          <1> 	call	isdir
  2181                              <1> 		; jsr r0,isdir / is it a directory
  2182 00003BFC E81E060000          <1> 	call	namei
  2183                              <1> 		; jsr r0,namei / no, get i-number of name2
  2184                              <1> 	;jnc	error
  2185                              <1> 		; br .+4   / not found 
  2186                              <1> 			 ; / so r1 = i-number of current directory
  2187                              <1> 			 ; / ii = i-number of current directory
  2188                              <1> 		; br error9 / file already exists., error
  2189 00003C01 720F                <1> 	jc	short syslink1
  2190                              <1> 	; pop eax ; 24/12/2021
  2191                              <1> 	; pop eax
  2192                              <1> 	; 'file exists !' error
  2193 00003C03 C705[ED680000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2193 00003C0B 0000                <1>
  2194 00003C0D E900F7FFFF          <1> 	jmp	error
  2195                              <1> syslink1:
  2196                              <1> 	;pop	cx
  2197                              <1> 	; 24/12/2021
  2198 00003C12 59                  <1> 	pop	ecx ; **
  2199                              <1> 	;cmp	cx, [cdev]
  2200 00003C13 3A0D[7B680000]      <1> 	cmp	cl, [cdev]
  2201                              <1> 	;jne	error
  2202                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2203                              <1> 			       ; / end of current directory
  2204                              <1> 	        ; bne error9
  2205 00003C19 740F                <1> 	je	short syslink2
  2206                              <1> 	; 'not same drive !' error
  2207 00003C1B C705[ED680000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2207 00003C23 0000                <1>
  2208 00003C25 E9E8F6FFFF          <1> 	jmp	error
  2209                              <1> syslink2:
  2210                              <1> 	;pop	eax ; 24/12/2021
  2211                              <1> 	;push	eax
  2212                              <1> 	; 24/12/2021
  2213 00003C2A 8B0424              <1> 	mov	eax, [esp] ; *
  2214 00003C2D 66A3[CA680000]      <1> 	mov	[u.dirbuf], ax
  2215                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2216 00003C33 E89E000000          <1> 	call	mkdir
  2217                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2218                              <1> 		 	     ; / in current directory
  2219                              <1> 	; 24/12/2021
  2220 00003C38 58                  <1> 	pop	eax ; *
  2221                              <1> 	;pop	ax
  2222                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2223 00003C39 E8F10D0000          <1> 	call	iget
  2224                              <1> 		; jsr r0,iget / get i-node into core
  2225 00003C3E FE05[96650000]      <1> 	inc	byte [i.nlks]
  2226                              <1> 		; incb i.nlks / add 1 to its number of links
  2227 00003C44 E8F00E0000          <1> 	call	setimod
  2228                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2229 00003C49 E9E4F6FFFF          <1> 	jmp	sysret
  2230                              <1> 
  2231                              <1> isdir:
  2232                              <1> 	; 03/02/2022
  2233                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2234                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2235                              <1> 	;
  2236                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2237                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2238                              <1> 	;  called by syslink and sysunlink to make sure directories
  2239                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2240                              <1> 	; 'isdir' does not bother checking. The current i-node
  2241                              <1> 	;  is not disturbed.			
  2242                              <1> 	;		
  2243                              <1> 	; INPUTS ->
  2244                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2245                              <1> 	;    u.uid - user id
  2246                              <1> 	; OUTPUTS ->
  2247                              <1> 	;    r1 - contains current i-number upon exit
  2248                              <1> 	;    	 (current i-node back in core) 
  2249                              <1> 	;	
  2250                              <1> 	; ((AX = R1))
  2251                              <1> 	;
  2252                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2253                              <1> 	;
  2254                              <1> 
  2255                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2256                              <1> 	; / there is an error unless super user made the call
  2257                              <1> 	
  2258 00003C4E 803D[E4680000]00    <1> 	cmp	byte [u.uid], 0 
  2259                              <1> 		; tstb u.uid / super user
  2260 00003C55 762B                <1> 	jna	short isdir1
  2261                              <1> 		; beq 1f / yes, don't care
  2262 00003C57 66FF35[78680000]    <1> 	push	word [ii]
  2263                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2264 00003C5E E8CC0D0000          <1> 	call	iget
  2265                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2266                              <1> 	; 03/02/2022
  2267 00003C63 F605[95650000]40    <1> 	test	byte [i.flgs+1], 40h
  2268                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2269                              <1> 		; bit $40000,i.flgs / is it a directory
  2270                              <1> 	;jnz	error
  2271                              <1> 		; bne error9 / yes, error
  2272 00003C6A 740F                <1> 	jz	short isdir0
  2273 00003C6C C705[ED680000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2273 00003C74 0000                <1>
  2274                              <1> 				; 'permission denied !' error
  2275                              <1> 	; pop	ax
  2276 00003C76 E997F6FFFF          <1> 	jmp	error	
  2277                              <1> isdir0:	
  2278 00003C7B 6658                <1> 	pop	ax
  2279                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2280 00003C7D E8AD0D0000          <1> 	call	iget
  2281                              <1> 		; jsr r0,iget / get it back in
  2282                              <1> isdir1: ; 1:
  2283 00003C82 C3                  <1> 	retn
  2284                              <1> 		; rts r0
  2285                              <1> 
  2286                              <1> sysunlink:
  2287                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2288                              <1> 	; 04/12/2015 (14 byte file names)
  2289                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2290                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2291                              <1> 	;
  2292                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2293                              <1> 	; name from its directory. If this entry was the last link
  2294                              <1> 	; to the file, the contents of the file are freed and the
  2295                              <1> 	; file is destroyed. If, however, the file was open in any
  2296                              <1> 	; process, the actual destruction is delayed until it is 
  2297                              <1> 	; closed, even though the directory entry has disappeared.
  2298                              <1> 	; 
  2299                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2300                              <1> 	; does not exist or that its directory can not be written.
  2301                              <1> 	; Write permission is not required on the file itself.
  2302                              <1> 	; It is also illegal to unlink a directory (except for
  2303                              <1> 	; the superuser).
  2304                              <1> 	;
  2305                              <1> 	; Calling sequence:
  2306                              <1> 	;	sysunlink; name
  2307                              <1> 	; Arguments:
  2308                              <1> 	;	name - name of directory entry to be removed 
  2309                              <1> 	; Inputs: -
  2310                              <1> 	; Outputs: -
  2311                              <1> 	; ...............................................................
  2312                              <1> 	;				
  2313                              <1> 	; Retro UNIX 8086 v1 modification:
  2314                              <1> 	;	 The user/application program puts address of the name
  2315                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2316                              <1> 
  2317                              <1> 	; / name - remove link name
  2318 00003C83 891D[B0680000]      <1> 	mov	[u.namep], ebx
  2319                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2320 00003C89 E891050000          <1> 	call	namei
  2321                              <1> 		; jsr r0,namei / find the i-number associated 
  2322                              <1> 			     ; / with the path name
  2323                              <1> 	;jc	error
  2324                              <1> 		; br error9 / not found
  2325 00003C8E 730F                <1> 	jnc	short sysunlink1
  2326                              <1> 	; 'file not found !' error
  2327 00003C90 C705[ED680000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2327 00003C98 0000                <1>
  2328 00003C9A E973F6FFFF          <1> 	jmp	error
  2329                              <1> sysunlink1:
  2330 00003C9F 50                  <1> 	push	eax ; 24/12/2021
  2331                              <1> 	;push	ax
  2332                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2333 00003CA0 E8A9FFFFFF          <1> 	call	isdir
  2334                              <1> 		; jsr r0,isdir / is it a directory
  2335                              <1> 	;xor 	ax, ax
  2336                              <1> 	; 24/12/2021
  2337 00003CA5 31C0                <1> 	xor	eax, eax
  2338 00003CA7 66A3[CA680000]      <1> 	mov	[u.dirbuf], ax ; 0
  2339                              <1> 		; clr u.dirbuf / no, clear the location that will
  2340                              <1> 			   ; / get written into the i-number portion
  2341                              <1> 			 ; / of the entry
  2342 00003CAD 832D[B4680000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2343                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2344 00003CB4 E868000000          <1> 	call	wdir
  2345                              <1> 		; jsr r0,wdir / free the directory entry
  2346 00003CB9 58                  <1> 	pop	eax ; 24/12/2021
  2347                              <1> 	;pop	ax
  2348                              <1> 		; mov (sp)+,r1 / get i-number back
  2349 00003CBA E8700D0000          <1> 	call	iget
  2350                              <1> 		; jsr r0,iget / get i-node
  2351 00003CBF E8750E0000          <1> 	call	setimod
  2352                              <1> 		; jsr r0,setimod / set modified flag
  2353 00003CC4 FE0D[96650000]      <1> 	dec	byte [i.nlks]
  2354                              <1> 		; decb i.nlks / decrement the number of links
  2355                              <1> 	; 24/12/2021
  2356 00003CCA 7505                <1> 	jnz	short sysunlink_2
  2357                              <1> 	;jnz	sysret
  2358                              <1> 		; bgt sysret9 / if this was not the last link
  2359                              <1> 			    ; / to file return
  2360                              <1> 	; AX = r1 = i-number
  2361 00003CCC E8B3090000          <1> 	call	anyi
  2362                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2363                              <1> 			 ; / Then free contents of file and destroy it.
  2364                              <1> sysunlink_2:
  2365 00003CD1 E95CF6FFFF          <1> 	jmp	sysret
  2366                              <1> 		; br sysret9
  2367                              <1> 
  2368                              <1> mkdir:
  2369                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2370                              <1> 	; 04/12/2015 (14 byte directory names)
  2371                              <1> 	; 12/10/2015
  2372                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2373                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2374                              <1> 	;
  2375                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2376                              <1> 	; by u.namep into the current directory.
  2377                              <1> 	;
  2378                              <1> 	; INPUTS ->
  2379                              <1> 	;    u.namep - points to a file name 
  2380                              <1> 	;	           that is about to be a directory entry.
  2381                              <1> 	;    ii - current directory's i-number.	
  2382                              <1> 	; OUTPUTS ->
  2383                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2384                              <1> 	;    u.off - points to entry to be filled 
  2385                              <1> 	;	     in the current directory		
  2386                              <1> 	;    u.base - points to start of u.dirbuf.
  2387                              <1> 	;    r1 - contains i-number of current directory 
  2388                              <1> 	;	
  2389                              <1> 	; ((AX = R1)) output
  2390                              <1> 	;
  2391                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2392                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2393                              <1> 	;
  2394                              <1> 
  2395                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2396 00003CD6 31C0                <1> 	xor 	eax, eax
  2397 00003CD8 BF[CC680000]        <1> 	mov     edi, u.dirbuf+2
  2398 00003CDD 89FE                <1> 	mov	esi, edi
  2399 00003CDF AB                  <1> 	stosd
  2400 00003CE0 AB                  <1> 	stosd
  2401                              <1> 	; 04/12/2015 (14 byte directory names)
  2402 00003CE1 AB                  <1> 	stosd
  2403 00003CE2 66AB                <1> 	stosw
  2404                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2405 00003CE4 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2406                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2407                              <1> 	;mov 	ebp, [u.namep]
  2408 00003CE6 E8B3060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2409                              <1> 		; esi = physical address (page start + offset)
  2410                              <1> 		; ecx = byte count in the page (1 - 4096)
  2411                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2412                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2413                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2414                              <1> mkdir_1: ; 1: 
  2415 00003CEB 45                  <1> 	inc	ebp ; 12/10/2015
  2416                              <1> 	;
  2417                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2418                              <1> 	 ; 01/08/2013
  2419 00003CEC AC                  <1> 	lodsb
  2420                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2421 00003CED 20C0                <1> 	and 	al, al
  2422 00003CEF 7426                <1> 	jz 	short mkdir_3 	  
  2423                              <1> 		; beq 1f / if null, done
  2424 00003CF1 3C2F                <1> 	cmp	al, '/'
  2425                              <1> 		; cmp r1,$'/ / is it a "/"?
  2426 00003CF3 7413                <1> 	je	short mkdir_err
  2427                              <1> 	;je	error
  2428                              <1> 		; beq error9 / yes, error
  2429                              <1> 	; 12/10/2015
  2430                              <1> 	;dec	cx
  2431 00003CF5 49                  <1> 	dec	ecx ; 24/12/2021
  2432 00003CF6 7505                <1> 	jnz	short mkdir_2
  2433                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2434 00003CF8 E8A7060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2435                              <1> 		; esi = physical address (page start + offset)
  2436                              <1> 		; ecx = byte count in the page
  2437                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2438                              <1> mkdir_2:
  2439 00003CFD 81FF[DA680000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2440                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2441                              <1> 				     ; / a char?
  2442 00003D03 74E6                <1> 	je	short mkdir_1
  2443                              <1> 		; beq 1b / yes, go back
  2444 00003D05 AA                  <1> 	stosb
  2445                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2446 00003D06 EBE3                <1> 	jmp 	short mkdir_1
  2447                              <1> 		; br 1b / get next char
  2448                              <1> mkdir_err:
  2449                              <1> 	; 17/06/2015
  2450 00003D08 C705[ED680000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2450 00003D10 0000                <1>
  2451 00003D12 E9FBF5FFFF          <1> 	jmp	error
  2452                              <1> 
  2453                              <1> mkdir_3: ; 1:
  2454 00003D17 A1[AC680000]        <1> 	mov	eax, [u.dirp]
  2455 00003D1C A3[B4680000]        <1> 	mov	[u.off], eax
  2456                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2457                              <1> 				 ; / slot to u.off
  2458                              <1> wdir: 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2459                              <1> 	; 29/04/2013
  2460 00003D21 C705[B8680000]-     <1>         mov     dword [u.base], u.dirbuf
  2460 00003D27 [CA680000]          <1>
  2461                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2462 00003D2B C705[BC680000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2462 00003D33 0000                <1>
  2463                              <1> 		; mov $10.,u.count / u.count = 10
  2464 00003D35 66A1[78680000]      <1> 	mov	ax, [ii] 
  2465                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2466 00003D3B B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2467 00003D3D E8C10D0000          <1> 	call 	access
  2468                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2469                              <1> 				 ; / for writing
  2470                              <1> 	; AX = i-number of current directory
  2471                              <1> 	; 01/08/2013
  2472 00003D42 FE05[FF680000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2473                              <1> 	;call	writei
  2474                              <1> 	;	; jsr r0,writei / write into directory
  2475                              <1> 	;retn	
  2476                              <1> 	;	; rts r0
  2477                              <1> 	; 24/12/2021
  2478 00003D48 E9A4100000          <1> 	jmp	writei
  2479                              <1> 
  2480                              <1> sysexec:
  2481                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2482                              <1> 	; 03/02/2022
  2483                              <1> 	; 12/01/2022
  2484                              <1> 	; 08/01/2022
  2485                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2486                              <1> 	; 23/10/2015
  2487                              <1> 	; 19/10/2015
  2488                              <1> 	; 10/10/2015, 18/10/2015
  2489                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2490                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2491                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2492                              <1> 	; 24/06/2015, 25/06/2015
  2493                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2494                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2495                              <1> 	;
  2496                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2497                              <1> 	; pointed to by 'name' in the sysexec call. 
  2498                              <1> 	; 'sysexec' performs the following operations:
  2499                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2500                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2501                              <1> 	;    3. sets trap vectors to system routines.
  2502                              <1> 	;    4. loads arguments to be passed to executing file into
  2503                              <1> 	;	highest locations of user's core
  2504                              <1> 	;    5. puts pointers to arguments in locations immediately
  2505                              <1> 	;	following arguments.
  2506                              <1> 	;    6.	saves number of arguments in next location.
  2507                              <1> 	;    7. initializes user's stack area so that all registers
  2508                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2509                              <1> 	;	to core when 'sysret' restores registers 
  2510                              <1> 	;	and does an rti.
  2511                              <1> 	;    8. inializes u.r0 and u.sp
  2512                              <1> 	;    9. zeros user's core down to u.r0
  2513                              <1> 	;   10.	reads executable file from storage device into core
  2514                              <1> 	;	starting at location 'core'.
  2515                              <1> 	;   11.	sets u.break to point to end of user's code with
  2516                              <1> 	;	data area appended.
  2517                              <1> 	;   12.	calls 'sysret' which returns control at location
  2518                              <1> 	;	'core' via 'rti' instruction. 		  		
  2519                              <1> 	;
  2520                              <1> 	; Calling sequence:
  2521                              <1> 	;	sysexec; namep; argp
  2522                              <1> 	; Arguments:
  2523                              <1> 	;	namep - points to pathname of file to be executed
  2524                              <1> 	;	argp  - address of table of argument pointers
  2525                              <1> 	;	argp1... argpn - table of argument pointers
  2526                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2527                              <1> 	; Inputs: (arguments)
  2528                              <1> 	; Outputs: -	
  2529                              <1> 	; ...............................................................
  2530                              <1> 	;
  2531                              <1> 	; Retro UNIX 386 v1 modification: 
  2532                              <1> 	;	User application runs in it's own virtual space 
  2533                              <1> 	;	which is izolated from kernel memory (and other
  2534                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2535                              <1> 	;	privilige mode. Virtual start address is always 0.
  2536                              <1> 	;	User's core memory starts at linear address 400000h
  2537                              <1> 	;	(the end of the 1st 4MB).
  2538                              <1> 	;
  2539                              <1> 	; Retro UNIX 8086 v1 modification: 
  2540                              <1> 	;	user/application segment and system/kernel segment
  2541                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2542                              <1> 	;	are different (user's registers are saved to 
  2543                              <1> 	;	and then restored from system's stack.)
  2544                              <1> 	;
  2545                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2546                              <1> 	;	      arguments which were in these registers;
  2547                              <1> 	;	      but, it returns by putting the 1st argument
  2548                              <1> 	;	      in 'u.namep' and the 2nd argument
  2549                              <1> 	;	      on top of stack. (1st argument is offset of the
  2550                              <1> 	;	      file/path name in the user's program segment.)		 	
  2551                              <1> 	
  2552                              <1> 	;call	arg2
  2553                              <1> 	; * name - 'u.namep' points to address of file/path name
  2554                              <1> 	;          in the user's program segment ('u.segmnt')
  2555                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2556                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2557                              <1> 	;          which is on top of stack.
  2558                              <1> 	;
  2559                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2560                              <1> 
  2561                              <1> 	; 23/06/2015 (32 bit modifications)
  2562                              <1> 
  2563 00003D4D 891D[B0680000]      <1> 	mov	[u.namep], ebx ; argument 1
  2564                              <1>         ; 18/10/2015
  2565 00003D53 890D[18690000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2566 00003D59 E8C1040000          <1> 	call	namei
  2567                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2568                              <1> 			     ; / named in sysexec call in r1
  2569                              <1> 	;jc	error
  2570                              <1> 		; br error9
  2571 00003D5E 731E                <1> 	jnc	short sysexec_0
  2572                              <1> 	;
  2573                              <1> 	; 'file not found !' error
  2574 00003D60 C705[ED680000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2574 00003D68 0000                <1>
  2575 00003D6A E9A3F5FFFF          <1> 	jmp	error 
  2576                              <1> sysexec_not_exf:
  2577                              <1> 	; 'not executable file !' error
  2578 00003D6F C705[ED680000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2578 00003D77 0000                <1>
  2579 00003D79 E994F5FFFF          <1> 	jmp	error 
  2580                              <1> sysexec_0:
  2581 00003D7E E8AC0C0000          <1> 	call	iget
  2582                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2583                              <1> 	; 24/12/2021
  2584 00003D83 F605[94650000]10    <1> 	test	byte [i.flgs], 10h
  2585                              <1> 	;test	word [i.flgs], 10h
  2586                              <1> 	;	; bit $20,i.flgs / is file executable
  2587 00003D8A 74E3                <1> 	jz	short sysexec_not_exf
  2588                              <1> 	;jz	error
  2589                              <1> 		; beq error9
  2590                              <1> 	;;
  2591 00003D8C E8F8140000          <1> 	call	iopen
  2592                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2593                              <1> 			     ; / given in r1 (opens file)
  2594                              <1> 	; AX = i-number of the file
  2595                              <1> 	; 24/12/2021
  2596 00003D91 F605[94650000]20    <1> 	test	byte [i.flgs], 20h
  2597                              <1> 	;test	word [i.flgs], 20h
  2598                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2599 00003D98 7415                <1> 	jz	short sysexec_1
  2600                              <1> 		; beq 1f
  2601 00003D9A 803D[E4680000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2602                              <1> 		; tstb u.uid / test user id
  2603 00003DA1 760C                <1> 	jna	short sysexec_1
  2604                              <1> 		; beq 1f / super user
  2605 00003DA3 8A0D[97650000]      <1> 	mov	cl, [i.uid]
  2606 00003DA9 880D[E4680000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2607                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2608                              <1> 				 ; / as process user id
  2609                              <1> sysexec_1:
  2610                              <1> 	; 03/02/2022
  2611                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2612                              <1> 	; 18/10/2215
  2613                              <1> 	; 10/10/2015
  2614                              <1> 	; 21/07/2015, 24/07/2015
  2615                              <1> 	; 24/06/2015, 25/06/2015
  2616                              <1>         ; Moving arguments to the end of [u.upage]
  2617                              <1> 	; (by regarding page borders in user's memory space)
  2618                              <1> 	;
  2619                              <1> 	; 10/10/2015
  2620                              <1> 	; 21/07/2015
  2621 00003DAF 89E5                <1> 	mov	ebp, esp ; (**)
  2622                              <1> 	; 18/10/2015
  2623 00003DB1 89EF                <1> 	mov 	edi, ebp
  2624 00003DB3 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2625                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2626 00003DB8 29CF                <1> 	sub	edi, ecx
  2627 00003DBA 89FC                <1> 	mov	esp, edi
  2628 00003DBC 31C0                <1> 	xor	eax, eax
  2629 00003DBE A3[C0680000]        <1> 	mov 	[u.nread], eax ; 0
  2630                              <1> 	; 12/01/2022
  2631                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2632                              <1> 	; may leave it with any value after an error))
  2633                              <1> 	;mov	[argc], ax
  2634 00003DC3 A2[16690000]        <1> 	mov	[argc], al ; 0
  2635                              <1> 	;
  2636 00003DC8 49                  <1> 	dec	ecx ; 256 - 1
  2637 00003DC9 890D[BC680000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2638                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2639                              <1> sysexec_2:
  2640 00003DCF 8B35[18690000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2641 00003DD5 E863020000          <1> 	call	get_argp
  2642                              <1> 	;mov	ecx, 4 
  2643                              <1> 	; 03/02/2022
  2644 00003DDA 31C9                <1> 	xor	ecx, ecx
  2645 00003DDC B104                <1> 	mov	cl, 4
  2646                              <1> sysexec_3:
  2647 00003DDE 21C0                <1> 	and	eax, eax
  2648 00003DE0 7455                <1> 	jz	short sysexec_6
  2649                              <1> 	; 18/10/2015
  2650 00003DE2 010D[18690000]      <1> 	add	[argv], ecx ; 4
  2651                              <1> 	;inc	word [argc]
  2652                              <1> 	; 12/01/2022 ; ([argc] < 32)
  2653 00003DE8 FE05[16690000]      <1> 	inc	byte [argc]
  2654                              <1> 	;
  2655 00003DEE A3[B8680000]        <1> 	mov	[u.base], eax
  2656                              <1>  	; 23/10/2015
  2657 00003DF3 66C705[FD680000]00- <1> 	mov	word [u.pcount], 0
  2657 00003DFB 00                  <1>
  2658                              <1> sysexec_4:
  2659 00003DFC E81A120000          <1> 	call	cpass ; get a character from user's core memory
  2660 00003E01 750B                <1>         jnz	short sysexec_5
  2661                              <1> 		; (max. 255 chars + null)
  2662                              <1> 	; 18/10/2015
  2663 00003E03 28C0                <1> 	sub 	al, al
  2664 00003E05 AA                  <1> 	stosb
  2665 00003E06 FF05[C0680000]      <1> 	inc	dword [u.nread]
  2666 00003E0C EB29                <1> 	jmp	short sysexec_6
  2667                              <1> sysexec_5:
  2668 00003E0E AA                  <1> 	stosb
  2669 00003E0F 20C0                <1> 	and 	al, al
  2670 00003E11 75E9                <1> 	jnz	short sysexec_4
  2671                              <1> 	;mov	ecx, 4
  2672                              <1> 	; 24/12/2021
  2673 00003E13 29C9                <1> 	sub	ecx, ecx
  2674 00003E15 B104                <1> 	mov	cl, 4
  2675                              <1> 	;cmp	[ncount], ecx ; 4
  2676                              <1> 	; 24/12/2021
  2677 00003E17 66390D[14690000]    <1> 	cmp	[ncount], cx ; 4
  2678 00003E1E 72AF                <1> 	jb	short sysexec_2
  2679 00003E20 8B35[10690000]      <1> 	mov	esi, [nbase]
  2680 00003E26 010D[10690000]      <1> 	add	[nbase], ecx ; 4	
  2681 00003E2C 66290D[14690000]    <1> 	sub	[ncount], cx 
  2682 00003E33 8B06                <1> 	mov	eax, [esi]
  2683 00003E35 EBA7                <1> 	jmp	short sysexec_3
  2684                              <1> sysexec_6:
  2685                              <1> 	; 18/10/2015
  2686                              <1> 	; argument list transfer from user's core memory to
  2687                              <1> 	; kernel stack frame is OK here.
  2688                              <1> 	; [u.nread] = ; argument list length
  2689                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2690                              <1> 	;
  2691                              <1> 	; 18/10/2015
  2692                              <1> 	; 24/07/2015
  2693                              <1>         ; 21/07/2015
  2694                              <1> 	; 02/07/2015
  2695                              <1> 	; 25/06/2015
  2696                              <1> 	; 24/06/2015
  2697                              <1> 	; 23/06/2015
  2698                              <1> 	;
  2699 00003E37 8B1D[F5680000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2700 00003E3D 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2701 00003E3F 740A                <1> 	jz	short sysexec_7
  2702 00003E41 A1[F1680000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2703 00003E46 E8E6E8FFFF          <1> 	call	deallocate_page_dir
  2704                              <1> sysexec_7:
  2705 00003E4B E816E8FFFF          <1> 	call	make_page_dir
  2706                              <1> 	;jc	short sysexec_14
  2707                              <1> 	;jc	panic  ; allocation error 
  2708                              <1> 		       ; after a deallocation would be nonsence !?
  2709                              <1> 	; 08/01/2022
  2710 00003E50 7243                <1> 	jc	short sysexec_panic
  2711                              <1> 
  2712                              <1> 	; 24/07/2015
  2713                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2714                              <1> 	;     of the user's page directory
  2715                              <1> 	;     (It is needed for interrupts!)
  2716                              <1> 	; 18/10/2015
  2717 00003E52 8B15[D8640000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2718 00003E58 8B02                <1> 	mov	eax, [edx] ; physical address of
  2719                              <1> 			   ; kernel's first page table (1st 4 MB)
  2720                              <1> 			   ; (PDE 0 of kernel's page directory)
  2721 00003E5A 8B15[F1680000]      <1> 	mov 	edx, [u.pgdir]
  2722 00003E60 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2723                              <1> 	;
  2724                              <1> 	; 20/07/2015
  2725 00003E62 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2726                              <1> 	; 18/10/2015
  2727 00003E67 BE[08690000]        <1> 	mov	esi, pcore ; physical start address
  2728                              <1> sysexec_8:	
  2729 00003E6C B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2730 00003E71 E80EE8FFFF          <1> 	call	make_page_table
  2731                              <1> 	;jc	panic
  2732                              <1> 	; 24/12/2021
  2733 00003E76 721D                <1> 	jc	short sysexec_panic
  2734                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2735 00003E78 E815E8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2736                              <1> 	;jc	panic
  2737                              <1> 	; 24/12/2021
  2738 00003E7D 7216                <1> 	jc	short sysexec_panic
  2739                              <1> 	;
  2740 00003E7F 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2741                              <1> 	; ebx = virtual address (24/07/2015)
  2742                              <1> 	; 24/12/2021
  2743                              <1> 	;call 	add_to_swap_queue
  2744                              <1> 	; 18/10/2015
  2745 00003E81 81FE[0C690000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2746 00003E87 7411                <1> 	je	short sysexec_9 ; yes
  2747 00003E89 BE[0C690000]        <1> 	mov	esi, ecore  ; physical address of the last page 
  2748                              <1> 	; 20/07/2015
  2749 00003E8E BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2750                              <1> 	; ebx = virtual end address + segment base address - 4K
  2751 00003E93 EBD7                <1>         jmp     short sysexec_8
  2752                              <1> 
  2753                              <1> sysexec_panic:
  2754                              <1> 	; 26/03/2021
  2755 00003E95 E937EDFFFF          <1> 	jmp	panic
  2756                              <1> 
  2757                              <1> sysexec_9:
  2758                              <1> 	; 18/10/2015
  2759                              <1> 	; 26/08/2015
  2760                              <1> 	; 25/06/2015
  2761                              <1> 	; move arguments from kernel stack to [ecore]
  2762                              <1> 	; (argument list/line will be copied from kernel stack
  2763                              <1> 	; frame to the last (stack) page of user's core memory)
  2764                              <1> 	; 18/10/2015
  2765 00003E9A 8B3D[0C690000]      <1> 	mov	edi, [ecore]
  2766 00003EA0 81C700100000        <1> 	add	edi, PAGE_SIZE
  2767                              <1> 	;movzx	eax, word [argc]
  2768                              <1> 	; 12/01/2022
  2769 00003EA6 31C0                <1> 	xor	eax, eax
  2770 00003EA8 A0[16690000]        <1> 	mov	al, [argc]
  2771 00003EAD 08C0                <1> 	or	al, al
  2772                              <1> 	;or	eax, eax
  2773 00003EAF 7509                <1> 	jnz	short sysexec_10
  2774 00003EB1 89FB                <1> 	mov 	ebx, edi
  2775 00003EB3 83EB04              <1> 	sub	ebx, 4 
  2776 00003EB6 8903                <1> 	mov	[ebx], eax ; 0
  2777 00003EB8 EB43                <1> 	jmp 	short sysexec_13
  2778                              <1> sysexec_10:
  2779 00003EBA 8B0D[C0680000]      <1> 	mov	ecx, [u.nread]
  2780                              <1> 	;mov 	esi, [argv]
  2781 00003EC0 89E6                <1> 	mov	esi, esp ; start address of argument list
  2782 00003EC2 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2783                              <1> 
  2784                              <1> 	;;;;
  2785                              <1> 	; 09/05/2022
  2786                              <1> 	; (move edi -backward- to dword boundary)
  2787                              <1> 	; ((this will prevent 'general protection fault' error
  2788                              <1> 	;  as result of a lodsd or dword move instruction
  2789                              <1> 	;  at the end of argument list))
  2790 00003EC4 83EF03              <1> 	sub	edi, 3
  2791 00003EC7 83E7FC              <1> 	and	edi, ~3 ; (*)
  2792                              <1> 	;;;
  2793                              <1> 
  2794 00003ECA 89C2                <1> 	mov	edx, eax
  2795                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2796 00003ECC FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2797 00003ECE C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2798                              <1> 	; edx <= 128
  2799 00003ED1 89FB                <1> 	mov	ebx, edi
  2800                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2801                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2802 00003ED3 29D3                <1> 	sub 	ebx, edx
  2803 00003ED5 89FA                <1> 	mov	edx, edi
  2804 00003ED7 F3A4                <1> 	rep	movsb
  2805 00003ED9 89D6                <1> 	mov 	esi, edx
  2806 00003EDB 89DF                <1> 	mov 	edi, ebx
  2807 00003EDD BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2808 00003EE2 2B15[0C690000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2809 00003EE8 AB                  <1> 	stosd	; eax = argument count	
  2810                              <1> sysexec_11:
  2811 00003EE9 89F0                <1> 	mov	eax, esi
  2812 00003EEB 01D0                <1> 	add	eax, edx
  2813 00003EED AB                  <1> 	stosd  ; eax = virtual address
  2814 00003EEE FE0D[16690000]      <1> 	dec	byte [argc]
  2815 00003EF4 7407                <1> 	jz	short sysexec_13
  2816                              <1> sysexec_12:
  2817 00003EF6 AC                  <1> 	lodsb
  2818 00003EF7 20C0                <1> 	and	al, al
  2819 00003EF9 75FB                <1> 	jnz	short sysexec_12
  2820 00003EFB EBEC                <1> 	jmp	short sysexec_11
  2821                              <1> 	;
  2822                              <1> 	; 1:
  2823                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2824                              <1> 			     ; / pointers to arguments to be passed
  2825                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2826                              <1> 			      ; / u.quit = 1 take quit
  2827                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2828                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2829                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2830                              <1> 			       ; / system routine
  2831                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2832                              <1> 			       ; / set to take system routine
  2833                              <1> 		; mov $sstack,sp / stack space used during swapping
  2834                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2835                              <1> 		; mov $ecore,r5 / r5 has end of core
  2836                              <1> 		; mov $core,r4 / r4 has start of users core
  2837                              <1> 		; mov r4,u.base / u.base has start of users core
  2838                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2839                              <1> 	; 1:
  2840                              <1> 		; tst (r2)+ / argument char = "nul"
  2841                              <1> 		; bne 1b
  2842                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2843                              <1> 			  ; / end of argument pointer list
  2844                              <1> 	; 1:
  2845                              <1> 	     ; / move arguments to bottom of users core
  2846                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2847                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2848                              <1> 			    ; / ptr list
  2849                              <1> 		; blo 1f / branch to 1f when all arguments
  2850                              <1> 		       ; / are moved
  2851                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2852                              <1> 	; 2:
  2853                              <1> 		; tstb (r3)+
  2854                              <1> 		; bne 2b / scan argument for \0 (nul)
  2855                              <1> 
  2856                              <1> 	; 2:
  2857                              <1> 		; movb -(r3),-(r5) / move argument char 
  2858                              <1> 				 ; / by char starting at "ecore"
  2859                              <1> 		; cmp r3,(r2) / moved all characters in 
  2860                              <1> 			    ; / this argument
  2861                              <1> 		; bhi 2b / branch 2b if not
  2862                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2863                              <1> 			     ; / r5 has pointer to nth arg
  2864                              <1> 		; br 1b / string
  2865                              <1> 	; 1:
  2866                              <1> 		; clrb -(r5)
  2867                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2868                              <1> 			; / last word of argument strings
  2869                              <1> 		; mov $core,r2
  2870                              <1> 	
  2871                              <1> 	; 1: / move argument pointers into core following 
  2872                              <1> 	      ; / argument strings
  2873                              <1> 		; cmp r2,r4
  2874                              <1> 		; bhis 1f / branch to 1f when all pointers
  2875                              <1> 			; / are moved
  2876                              <1> 		; mov (r2)+,-(r5)
  2877                              <1> 		; br 1b
  2878                              <1> 	; 1:
  2879                              <1> 		; sub $core,r4 / gives number of arguments *2
  2880                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2881                              <1> 		       ; / the number of args stored
  2882                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2883                              <1> 			     ; / of the argument pointers
  2884                              <1> sysexec_13:
  2885                              <1> 	; 19/10/2015
  2886                              <1> 	; 18/10/2015
  2887                              <1> 	; 29/07/2015
  2888                              <1> 	; 25/07/2015
  2889                              <1> 	; 24/07/2015
  2890                              <1> 	; 20/07/2015
  2891                              <1> 	; 25/06/2015
  2892                              <1> 	; 24/06/2015
  2893                              <1> 	; 23/06/2015
  2894                              <1> 	;
  2895                              <1> 	; moving arguments to [ecore] is OK here..
  2896                              <1> 	; 18/10/2015
  2897 00003EFD 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2898                              <1> 	; ebx = beginning addres of argument list pointers
  2899                              <1> 	;	in user's stack
  2900                              <1> 	; 19/10/2015
  2901 00003EFF 2B1D[0C690000]      <1> 	sub 	ebx, [ecore]
  2902 00003F05 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2903                              <1> 			; end of core - 4096 (last page)
  2904                              <1> 			; (virtual address)
  2905 00003F0B 891D[18690000]      <1> 	mov	[argv], ebx
  2906 00003F11 891D[C4680000]      <1> 	mov	[u.break], ebx ; available user memory
  2907                              <1> 	;
  2908 00003F17 29C0                <1> 	sub	eax, eax
  2909 00003F19 C705[BC680000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2909 00003F21 0000                <1>
  2910                              <1> 		; mov $14,u.count
  2911 00003F23 C705[A8680000]-     <1> 	mov	dword [u.fofp], u.off
  2911 00003F29 [B4680000]          <1>
  2912                              <1> 		; mov $u.off,u.fofp
  2913 00003F2D A3[B4680000]        <1> 	mov	[u.off], eax ; 0
  2914                              <1> 		; clr u.off / set offset in file to be read to zero
  2915                              <1> 	; 25/07/2015
  2916 00003F32 A3[B8680000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2917                              <1> 	; 25/06/2015 
  2918 00003F37 66A1[78680000]      <1> 	mov	ax, [ii]
  2919                              <1> 	; AX = i-number of the executable file
  2920 00003F3D E8C10C0000          <1> 	call	readi
  2921                              <1> 		; jsr r0,readi / read in first six words of 
  2922                              <1> 			; / user's file, starting at $core
  2923                              <1> 		; mov sp,r5 / put users stack address in r5
  2924                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2925                              <1> 				; / from r5 (leaves number of words
  2926                              <1> 				; / less 26 available for
  2927                              <1> 			     	; / program in user core
  2928                              <1> 		; mov r5,u.count /
  2929                              <1> 	; 25/06/2015
  2930 00003F42 8B0D[C4680000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2931 00003F48 890D[BC680000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2932                              <1> 	;
  2933 00003F4E 8B0D[C0680000]      <1> 	mov	ecx, [u.nread]
  2934 00003F54 890D[C4680000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2935 00003F5A 80F920              <1> 	cmp	cl, 32
  2936 00003F5D 7540                <1>         jne     short sysexec_15
  2937                              <1> 	;:
  2938                              <1> 	; 25/06/2015
  2939                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2940                              <1> 	; 18/10/2015
  2941 00003F5F 8B35[08690000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2942                              <1> 		             ; (phys. start addr. of the exec. file)
  2943 00003F65 AD                  <1> 	lodsd
  2944 00003F66 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2945 00003F6A 7533                <1> 	jne	short sysexec_15
  2946                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2947                              <1> 			      ; / if file is standard a.out format
  2948                              <1> 		; bne 1f / branch, if not standard format
  2949 00003F6C AD                  <1> 	lodsd
  2950 00003F6D 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2951 00003F6F AD                  <1> 	lodsd
  2952 00003F70 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2953                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2954                              <1> 		              ; / number of bytes in program text	
  2955                              <1> 		; sub $14,r5 / subtract 12
  2956 00003F72 89CB                <1> 	mov	ebx, ecx
  2957                              <1> 	;
  2958                              <1> 	; 25/06/2015
  2959                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2960                              <1> 	;	and SINGLIX operating systems (as code template).
  2961                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2962                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2963                              <1> 	;	Overrun is not possible for current version. 	
  2964                              <1> 	;
  2965 00003F74 AD                  <1> 	lodsd	
  2966 00003F75 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2967 00003F77 3B1D[BC680000]      <1> 	cmp	ebx, [u.count]
  2968 00003F7D 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2969                              <1> 	;
  2970                              <1> 	; 24/07/2015
  2971                              <1> 	; add bss section size to [u.break]
  2972 00003F7F 0105[C4680000]      <1> 	add 	[u.break], eax
  2973                              <1> 	;
  2974 00003F85 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2975                              <1> 	;cmp	ecx, [u.count]
  2976                              <1> 	;jnb	short sysexec_16
  2977                              <1> 		; cmp r5,u.count /
  2978                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2979 00003F88 890D[BC680000]      <1> 	mov	[u.count], ecx ; required read count
  2980                              <1> 		; mov r5,u.count
  2981                              <1> 	;
  2982 00003F8E EB2A                <1> 	jmp	short sysexec_16
  2983                              <1> 	;
  2984                              <1> sysexec_14:
  2985                              <1> 	; 23/06/2015
  2986                              <1> 	; insufficient (out of) memory
  2987 00003F90 C705[ED680000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2987 00003F98 0000                <1>
  2988 00003F9A E973F3FFFF          <1> 	jmp	error
  2989                              <1> 	;
  2990                              <1> sysexec_15:
  2991                              <1> 	; 25/06/2015
  2992 00003F9F 0FB715[98650000]    <1>         movzx   edx, word [i.size] ; file size
  2993 00003FA6 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2994 00003FA8 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2995 00003FAA 01D1                <1> 	add	ecx, edx ; [i.size]
  2996 00003FAC 3B0D[BC680000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2997 00003FB2 77DC                <1> 	ja	short sysexec_14
  2998 00003FB4 8915[BC680000]      <1> 	mov	[u.count], edx
  2999                              <1> sysexec_16:
  3000 00003FBA 66A1[78680000]      <1> 	mov	ax, [ii] ; i-number
  3001 00003FC0 E83E0C0000          <1> 	call	readi
  3002                              <1> 		; add core+10,u.nread / add size of user data area 
  3003                              <1> 		                    ; / to u.nread
  3004                              <1> 		; br 2f
  3005                              <1> 	; 1:
  3006                              <1> 		; jsr r0,readi / read in rest of file
  3007                              <1> 	; 2:
  3008 00003FC5 8B0D[C0680000]      <1> 	mov	ecx, [u.nread]
  3009 00003FCB 010D[C4680000]      <1> 	add	[u.break], ecx
  3010                              <1> 		; mov u.nread,u.break / set users program break to end of 
  3011                              <1> 				    ; / user code
  3012                              <1> 		; add $core+14,u.break / plus data area
  3013                              <1> sysexec_17: ; 20/07/2015
  3014                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3015                              <1> 	; ('iclose' is not needed for regular files, from now on)
  3016                              <1> 	;;mov	ax, [ii] ; i-number
  3017                              <1> 	;call	iclose
  3018                              <1> 	;	; jsr r0,iclose / does nothing
  3019 00003FD1 31C0                <1>         xor     eax, eax
  3020 00003FD3 FEC0                <1> 	inc	al
  3021 00003FD5 66A3[DC680000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3022 00003FDB 66A3[DE680000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3023                              <1> 	; 02/07/2015
  3024 00003FE1 833D[F5680000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  3025 00003FE8 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3026                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3027 00003FEA 8B15[D8640000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3028 00003FF0 8915[F5680000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  3029                              <1> sysexec_18:
  3030                              <1> 	; 18/10/2015
  3031                              <1> 	; 05/08/2015
  3032                              <1> 	; 29/07/2015
  3033 00003FF6 8B2D[18690000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  3034                              <1> 			    ; list pointers (argument count)
  3035 00003FFC FA                  <1> 	cli
  3036 00003FFD 8B25[74640000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3037                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3038                              <1> 			    ; for this process	 
  3039                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3040                              <1> 	;xor	eax, eax ; 0
  3041 00004003 FEC8                <1> 	dec	al ; eax = 0
  3042 00004005 66BA2300            <1> 	mov	dx, UDATA
  3043 00004009 6652                <1> 	push	dx  ; user's stack segment
  3044 0000400B 55                  <1> 	push	ebp ; user's stack pointer
  3045                              <1> 		    ; (points to number of arguments)
  3046 0000400C FB                  <1> 	sti
  3047 0000400D 9C                  <1> 	pushfd	; EFLAGS
  3048                              <1> 		; Set IF for enabling interrupts in user mode	
  3049                              <1> 	;or	dword [esp], 200h 
  3050                              <1> 	;
  3051                              <1> 	;mov	bx, UCODE
  3052                              <1> 	;push	bx ; user's code segment
  3053 0000400E 6A1B                <1> 	push	UCODE
  3054                              <1> 	;push	0
  3055 00004010 50                  <1> 	push	eax ; EIP (=0) - start address -	
  3056                              <1> 		; clr -(r5) / popped into ps when rti in 
  3057                              <1> 			  ; / sysrele is executed
  3058                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3059                              <1> 		                ; / in sysrele is executed
  3060                              <1> 		;mov r5,0f / load second copyz argument
  3061                              <1> 		;tst -(r5) / decrement r5
  3062 00004011 8925[90680000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3063                              <1> 	; 05/08/2015
  3064                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3065                              <1> 	; ('push dx' would cause to general protection fault, 
  3066                              <1> 	; after 'pop ds' etc.)
  3067                              <1> 	;
  3068                              <1> 	;; push dx ; ds (UDATA)
  3069                              <1> 	;; push dx ; es (UDATA)
  3070                              <1> 	;; push dx ; fs (UDATA)
  3071                              <1> 	;; push dx ; gs (UDATA)
  3072                              <1> 	;
  3073                              <1> 	; This is a trick to prevent general protection fault
  3074                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3075 00004017 8EC2                <1> 	mov 	es, dx ; UDATA
  3076 00004019 06                  <1> 	push 	es ; ds (UDATA)
  3077 0000401A 06                  <1> 	push 	es ; es (UDATA)
  3078 0000401B 06                  <1> 	push 	es ; fs (UDATA)
  3079 0000401C 06                  <1> 	push	es ; gs (UDATA)
  3080 0000401D 66BA1000            <1> 	mov	dx, KDATA
  3081 00004021 8EC2                <1> 	mov	es, dx
  3082                              <1> 	;
  3083                              <1> 	;; pushad simulation
  3084 00004023 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3085 00004025 50                  <1> 	push	eax ; eax (0)
  3086 00004026 50                  <1> 	push	eax ; ecx (0)
  3087 00004027 50                  <1> 	push	eax ; edx (0)
  3088 00004028 50                  <1> 	push	eax ; ebx (0)
  3089 00004029 55                  <1> 	push	ebp ; esp before pushad
  3090 0000402A 50                  <1> 	push	eax ; ebp (0)
  3091 0000402B 50                  <1> 	push	eax ; esi (0)		
  3092 0000402C 50                  <1> 	push	eax ; edi (0)	
  3093                              <1> 	;
  3094 0000402D A3[98680000]        <1> 	mov	[u.r0], eax ; eax = 0
  3095 00004032 8925[94680000]      <1> 	mov	[u.usp], esp
  3096                              <1> 		; mov r5,u.r0 /
  3097                              <1> 		; sub $16.,r5 / skip 8 words
  3098                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3099                              <1> 		;             / effectively zeroes all regs
  3100                              <1> 			    ; / when sysrele is executed
  3101                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3102                              <1> 		; clr u.break
  3103                              <1> 		; mov r5,sp / point sp to user's stack
  3104                              <1> 	;
  3105 00004038 E9F7F2FFFF          <1> 	jmp	sysret0
  3106                              <1> 	;jmp	sysret
  3107                              <1> 		; br sysret3 / return to core image at $core
  3108                              <1> 
  3109                              <1> get_argp:
  3110                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3111                              <1> 	; 18/10/2015 (nbase, ncount)
  3112                              <1> 	; 21/07/2015
  3113                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3114                              <1> 	; Get (virtual) address of argument from user's core memory
  3115                              <1> 	;
  3116                              <1> 	; INPUT:
  3117                              <1> 	;	esi = virtual address of argument pointer
  3118                              <1> 	; OUTPUT:
  3119                              <1> 	;	eax = virtual address of argument
  3120                              <1> 	;
  3121                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3122                              <1> 	;
  3123 0000403D 833D[F5680000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3124                              <1> 				    ; (the caller is kernel)
  3125                              <1> 	;jna	short get_argpk 
  3126                              <1> 	; 24/12/2021
  3127 00004044 7719                <1> 	ja	short get_argp5
  3128                              <1> get_argpk:
  3129                              <1> 	; Argument is in kernel's memory space
  3130 00004046 66C705[14690000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3130 0000404E 10                  <1>
  3131 0000404F 8935[10690000]      <1> 	mov	[nbase], esi
  3132 00004055 8305[10690000]04    <1> 	add	dword [nbase], 4
  3133 0000405C 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3134 0000405E C3                  <1> 	retn
  3135                              <1> get_argp5:
  3136 0000405F 89F3                <1>      	mov	ebx, esi
  3137 00004061 E887E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3138 00004066 7257                <1>         jc      short get_argp_err ; 24/12/2021 (short jump)
  3139 00004068 A3[10690000]        <1> 	mov 	[nbase], eax ; physical address	
  3140 0000406D 66890D[14690000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3141 00004074 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3142                              <1> 	;cmp	cx, ax ; 4
  3143 00004079 39C1                <1> 	cmp	ecx, eax ; 24/12/2021
  3144 0000407B 734C                <1> 	jnb	short get_argp2
  3145 0000407D 89F3                <1> 	mov	ebx, esi
  3146 0000407F 01CB                <1> 	add	ebx, ecx
  3147 00004081 E867E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3148 00004086 7237                <1> 	jc	short get_argp_err
  3149                              <1> 	;push	esi
  3150 00004088 89C6                <1> 	mov	esi, eax
  3151 0000408A 66870D[14690000]    <1> 	xchg	cx, [ncount]
  3152 00004091 8735[10690000]      <1> 	xchg	esi, [nbase]
  3153 00004097 B504                <1> 	mov	ch, 4
  3154 00004099 28CD                <1> 	sub	ch, cl
  3155                              <1> get_argp0:
  3156 0000409B AC                  <1> 	lodsb
  3157                              <1> 	;push	ax
  3158                              <1> 	; 24/12/2021
  3159 0000409C 50                  <1> 	push	eax
  3160 0000409D FEC9                <1> 	dec	cl
  3161 0000409F 75FA                <1>         jnz     short get_argp0
  3162 000040A1 8B35[10690000]      <1> 	mov	esi, [nbase]
  3163                              <1> 	; 21/07/2015
  3164 000040A7 0FB6C5              <1> 	movzx	eax, ch
  3165 000040AA 0105[10690000]      <1> 	add	[nbase], eax
  3166 000040B0 662905[14690000]    <1> 	sub	[ncount], ax
  3167                              <1> get_argp1:
  3168 000040B7 AC                  <1> 	lodsb
  3169 000040B8 FECD                <1> 	dec	ch
  3170 000040BA 7423                <1>         jz      short get_argp3
  3171                              <1> 	;push	ax
  3172                              <1> 	; 24/12/2021
  3173 000040BC 50                  <1> 	push	eax
  3174 000040BD EBF8                <1> 	jmp     short get_argp1
  3175                              <1> 	; 24/12/2021
  3176                              <1> get_argp_err:
  3177 000040BF A3[ED680000]        <1> 	mov	[u.error], eax
  3178 000040C4 E949F2FFFF          <1> 	jmp	error
  3179                              <1> get_argp2:
  3180                              <1> 	; 21/07/2015
  3181                              <1> 	;mov	eax, 4
  3182 000040C9 8B15[10690000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3183 000040CF 0105[10690000]      <1> 	add	[nbase], eax
  3184 000040D5 662905[14690000]    <1> 	sub	[ncount], ax
  3185                              <1> 	;
  3186 000040DC 8B02                <1> 	mov	eax, [edx]
  3187 000040DE C3                  <1> 	retn
  3188                              <1> get_argp3:
  3189 000040DF B103                <1> 	mov	cl, 3
  3190                              <1> get_argp4:
  3191 000040E1 C1E008              <1> 	shl	eax, 8
  3192                              <1> 	;pop	dx
  3193                              <1> 	; 24/12/2021
  3194 000040E4 5A                  <1> 	pop	edx
  3195 000040E5 88D0                <1> 	mov 	al, dl
  3196 000040E7 E2F8                <1>         loop    get_argp4
  3197                              <1> 	;pop	esi
  3198 000040E9 C3                  <1> 	retn	
  3199                              <1> 
  3200                              <1> sysfstat:
  3201                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3202                              <1> 	;	([idev] return in eax)
  3203                              <1> 	;	0 = root device
  3204                              <1> 	;	1 = mounted device (>0)
  3205                              <1> 	; 03/02/2022
  3206                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3207                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3208                              <1> 	;
  3209                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3210                              <1> 	; on open files instead of files given by name. It puts the
  3211                              <1> 	; buffer address on the stack, gets the i-number and
  3212                              <1> 	; checks to see if the file is open for reading or writing.
  3213                              <1> 	; If the file is open for writing (i-number is negative)
  3214                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3215                              <1> 	; is made.	
  3216                              <1> 	;
  3217                              <1> 	; Calling sequence:
  3218                              <1> 	;	sysfstat; buf
  3219                              <1> 	; Arguments:
  3220                              <1> 	;	buf - buffer address
  3221                              <1> 	;
  3222                              <1> 	; Inputs: *u.r0 - file descriptor
  3223                              <1> 	; Outputs: buffer is loaded with file information
  3224                              <1> 	; ...............................................................
  3225                              <1> 	;				
  3226                              <1> 	; Retro UNIX 8086 v1 modification:
  3227                              <1> 	;       'sysfstat' system call has two arguments; so,
  3228                              <1> 	;	* 1st argument, file descriptor is in BX register
  3229                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3230                              <1> 
  3231                              <1> 	; / set status of open file
  3232                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3233 000040EA 51                  <1> 	push	ecx
  3234                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3235                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3236                              <1> 		; jsr r0,getf / get the files i-number
  3237                              <1> 	; BX = file descriptor (file number)
  3238 000040EB E8FE000000          <1> 	call	getf1
  3239                              <1> 	; 03/02/2022
  3240 000040F0 21C0                <1> 	and	eax, eax
  3241                              <1> 	;and	ax, ax ; i-number of the file
  3242                              <1> 		; tst	r1 / is it 0?
  3243                              <1> 	;jz	error
  3244                              <1> 		; beq error3 / yes, error
  3245 000040F2 750F                <1> 	jnz	short sysfstat1
  3246 000040F4 C705[ED680000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3246 000040FC 0000                <1>
  3247 000040FE E90FF2FFFF          <1> 	jmp	error
  3248                              <1> sysfstat1:
  3249 00004103 80FC80              <1> 	cmp	ah, 80h
  3250 00004106 7222                <1>         jb      short sysstat1
  3251                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3252 00004108 66F7D8              <1> 	neg	ax
  3253                              <1> 		; neg r1 / make it positive, then branch
  3254 0000410B EB1D                <1> 	jmp	short sysstat1
  3255                              <1> 		; br 1f / to 1f
  3256                              <1> sysstat:
  3257                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3258                              <1> 	;	([idev] return in eax)
  3259                              <1> 	;	0 = root device
  3260                              <1> 	;	1 = mounted device (>0)
  3261                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3262                              <1> 	; 18/10/2015
  3263                              <1> 	; 07/10/2015
  3264                              <1> 	; 02/09/2015
  3265                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3266                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3267                              <1> 	;
  3268                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3269                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3270                              <1> 	; long and information about the file placed in it.	
  3271                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3272                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3273                              <1> 	; is then loaded and the results are given in the UNIX
  3274                              <1> 	; Programmers Manual sysstat (II).	
  3275                              <1> 	;
  3276                              <1> 	; Calling sequence:
  3277                              <1> 	;	sysstat; name; buf
  3278                              <1> 	; Arguments:
  3279                              <1> 	;	name - points to the name of the file
  3280                              <1> 	;	buf - address of a 34 bytes buffer
  3281                              <1> 	; Inputs: -
  3282                              <1> 	; Outputs: buffer is loaded with file information
  3283                              <1> 	; ...............................................................
  3284                              <1> 	;				
  3285                              <1> 	; Retro UNIX 8086 v1 modification: 
  3286                              <1> 	;       'sysstat' system call has two arguments; so,
  3287                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3288                              <1> 	;	to get sysstat system call arguments from the user;
  3289                              <1> 	;	* 1st argument, name is pointed to by BX register
  3290                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3291                              <1> 	;
  3292                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3293                              <1> 	;	      arguments which were in these registers;
  3294                              <1> 	;	      but, it returns by putting the 1st argument
  3295                              <1> 	;	      in 'u.namep' and the 2nd argument
  3296                              <1> 	;	      on top of stack. (1st argument is offset of the
  3297                              <1> 	;	      file/path name in the user's program segment.)		 	
  3298                              <1> 	
  3299                              <1> 	; / ; name of file; buffer - get files status
  3300                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3301 0000410D 891D[B0680000]      <1> 	mov	[u.namep], ebx
  3302 00004113 51                  <1> 	push	ecx
  3303 00004114 E806010000          <1> 	call	namei
  3304                              <1> 		; jsr r0,namei / get the i-number for the file
  3305                              <1> 	;jc	error
  3306                              <1> 		; br error3 / no such file, error
  3307 00004119 730F                <1> 	jnc	short sysstat1
  3308                              <1> 	; pop 	ecx
  3309                              <1> sysstat_err0:
  3310                              <1> 	; 'file not found !' error
  3311 0000411B C705[ED680000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3311 00004123 0000                <1>
  3312 00004125 E9E8F1FFFF          <1> 	jmp	error
  3313                              <1> 
  3314                              <1> ;statx: db 0
  3315                              <1> 
  3316                              <1> sysstat1: ; 1:
  3317 0000412A E800090000          <1> 	call	iget
  3318                              <1> 		; jsr r0,iget / get the i-node into core
  3319                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3320                              <1> 	; 02/09/2015
  3321 0000412F 8F05[B8680000]      <1> 	pop	dword [u.base]
  3322                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3323 00004135 E861000000          <1> 	call	sysstat_gpa ; get physical address
  3324 0000413A 730A                <1> 	jnc 	short sysstat2
  3325                              <1> sysstat_err1:
  3326 0000413C A3[ED680000]        <1> 	mov	dword [u.error], eax ; error code
  3327 00004141 E9CCF1FFFF          <1> 	jmp	error
  3328                              <1> sysstat2:
  3329 00004146 A0[78680000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3330 0000414B AA                  <1> 	stosb
  3331 0000414C FF05[B8680000]      <1> 	inc 	dword [u.base]
  3332                              <1> 	;dec 	cx
  3333                              <1> 	; 24/12/2021
  3334 00004152 49                  <1> 	dec	ecx
  3335 00004153 7505                <1> 	jnz	short sysstat3
  3336 00004155 E841000000          <1> 	call	sysstat_gpa
  3337                              <1> 	;jc	short sysstat_err1
  3338                              <1> sysstat3:
  3339 0000415A A0[79680000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3340 0000415F AA                  <1> 	stosb
  3341                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3342 00004160 FF05[B8680000]      <1> 	inc 	dword [u.base]
  3343                              <1> 	;;dec 	word [u.pcount]
  3344                              <1> 	;dec	cx
  3345 00004166 49                  <1> 	dec	ecx ; 24/12/2021
  3346 00004167 7505                <1> 	jnz	short sysstat4
  3347 00004169 E82D000000          <1> 	call	sysstat_gpa
  3348                              <1> 	;jc	short sysstat_err1	
  3349                              <1> sysstat4:
  3350 0000416E BE[94650000]        <1> 	mov	esi, inode
  3351                              <1> 		; mov $inode,r2 / r2 points to i-node
  3352                              <1> sysstat5: ; 1:
  3353 00004173 A4                  <1> 	movsb
  3354                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3355 00004174 FF05[B8680000]      <1> 	inc 	dword [u.base]
  3356                              <1> 	;;dec 	word [u.pcount]
  3357                              <1> 	;dec 	cx
  3358                              <1> 	; 24/12/2021
  3359 0000417A 49                  <1> 	dec	ecx
  3360 0000417B 7505                <1> 	jnz	short sysstat6
  3361 0000417D E819000000          <1> 	call	sysstat_gpa
  3362                              <1> 	;jc	short sysstat_err1
  3363                              <1> sysstat6:		
  3364 00004182 81FE[B4650000]      <1> 	cmp	esi, inode + 32
  3365                              <1> 		; cmp r2,$inode+32 / done?
  3366 00004188 75E9                <1> 	jne	short sysstat5
  3367                              <1> 		; bne 1b / no, go back
  3368                              <1> 
  3369                              <1> 	;;;
  3370                              <1> 	; 09/05/2022
  3371                              <1> 	;*** additional feature *** -retro unix only- 
  3372                              <1> 	;
  3373                              <1> 	; !! return device number -of current inode- in eax !!
  3374                              <1> 	;
  3375                              <1> 	; (modification reason/purpose:
  3376                              <1> 	; to improve 'pwd' command's pathname output/result
  3377                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3378                              <1> 	; error due to same inode numbers in root file system
  3379                              <1> 	; and mounted file system.)
  3380                              <1> 	;
  3381 0000418A 29C0                <1> 	sub	eax, eax
  3382 0000418C A0[7A680000]        <1> 	mov	al, [idev] ; [cdev]
  3383 00004191 A3[98680000]        <1> 	mov	[u.r0], eax
  3384                              <1> 	;;;  
  3385                              <1> 
  3386 00004196 E997F1FFFF          <1> 	jmp	sysret
  3387                              <1> 		; br sysret3 / return through sysret
  3388                              <1> 	;
  3389                              <1> sysstat_gpa: ; get physical address of file status buffer
  3390                              <1> 	; 02/09/2015
  3391 0000419B 8B1D[B8680000]      <1> 	mov 	ebx, [u.base]
  3392                              <1> 	; 07/10/2015
  3393 000041A1 E847E8FFFF          <1> 	call	get_physical_addr ; get physical address
  3394                              <1> 	;jc	short sysstat_gpa1
  3395 000041A6 7294                <1> 	jc	short sysstat_err1
  3396                              <1> 	; 18/10/2015
  3397 000041A8 89C7                <1> 	mov	edi, eax ; physical address
  3398                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3399                              <1> ;sysstat_gpa1:
  3400 000041AA C3                  <1> 	retn
  3401                              <1> 
  3402                              <1> fclose:
  3403                              <1> 	; 08/01/2022
  3404                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3405                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3406                              <1> 	;            (32 bit offset pointer modification)
  3407                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3408                              <1> 	;
  3409                              <1> 	; Given the file descriptor (index to the u.fp list)
  3410                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3411                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3412                              <1> 	; u.fp list is cleared. If all the processes that opened
  3413                              <1> 	; that file close it, then fsp etry is freed and the file
  3414                              <1> 	; is closed. If not a return is taken. 
  3415                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3416                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3417                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3418                              <1> 	; a check is made to see if the file is special.	
  3419                              <1> 	;
  3420                              <1> 	; INPUTS ->
  3421                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3422                              <1> 	;    u.fp - list of entries in the fsp table
  3423                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3424                              <1> 	; OUTPUTS ->
  3425                              <1> 	;    r1 - contains the same file descriptor
  3426                              <1> 	;    r2 - contains i-number
  3427                              <1> 	;
  3428                              <1> 	; ((AX = R1))
  3429                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3430                              <1> 	;
  3431                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3432                              <1> 	;              if i-number of the file is 0. (error)  	
  3433                              <1> 
  3434                              <1> 	;movzx	edx, ax ; **
  3435                              <1> 	; 24/12/2021
  3436                              <1> 	;movzx	edx, al
  3437 000041AB 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 24/12/2021
  3438 000041AD 50                  <1> 	push	eax ; ***
  3439                              <1> 	;push	ax ; ***
  3440                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3441                              <1> 			     ; / the index to u.fp list)
  3442 000041AE E839000000          <1> 	call	getf
  3443                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3444                              <1> 			    ; / cdev has device =, u.fofp 
  3445                              <1> 			    ; / points to 3rd word of fsp entry
  3446 000041B3 6683F801            <1> 	cmp	ax, 1 ; r1
  3447                              <1> 		; tst r1 / is i-number 0?
  3448 000041B7 7231                <1> 	jb	short fclose_2
  3449                              <1> 		; beq 1f / yes, i-node not active so return
  3450                              <1> 		; tst (r0)+ / no, jump over error return
  3451 000041B9 89D3                <1> 	mov	ebx, edx ; **
  3452                              <1> 	; 24/12/2021
  3453 000041BB 89C2                <1> 	mov	edx, eax ; *
  3454                              <1> 	;mov 	dx, ax ; *
  3455                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3456                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3457                              <1> 			    ; / which is index to u.fp ; **
  3458 000041BD C683[9E680000]00    <1> 	mov	byte [ebx+u.fp], 0
  3459                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3460 000041C4 8B1D[A8680000]      <1> 	mov	ebx, [u.fofp]
  3461                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3462                              <1> fclose_0:
  3463 000041CA FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3464                              <1> 		; decb 2(r1) / decrement the number of processes 
  3465                              <1> 			   ; / that have opened the file
  3466 000041CD 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3467                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3468                              <1> 	;
  3469                              <1> 	; 24/12/2021
  3470 000041CF 52                  <1> 	push	edx ; *
  3471                              <1> 	;push	dx ; *
  3472                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3473                              <1> 	;xor	ax, ax ; 0
  3474                              <1> 	; 24/12/2021
  3475 000041D0 31C0                <1> 	xor	eax, eax
  3476 000041D2 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3477                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3478 000041D6 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3479                              <1> 		; tstb	3(r1) / has this file been deleted
  3480 000041D9 20C0                <1> 	and	al, al
  3481 000041DB 7407                <1> 	jz	short fclose_1
  3482                              <1> 		; beq 2f / no, branch
  3483                              <1> 	; 08/01/2022
  3484 000041DD 89D0                <1> 	mov	eax, edx
  3485                              <1> 	;mov	ax, dx ; *
  3486                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3487                              <1> 	; AX = inode number
  3488 000041DF E8A0040000          <1> 	call	anyi
  3489                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3490                              <1> 			    ; / check if file appears in fsp again
  3491                              <1> fclose_1: ; 2:
  3492                              <1> 	; 24/12/2021
  3493 000041E4 58                  <1> 	pop	eax ; * 
  3494                              <1> 	;pop	ax ; *
  3495                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3496 000041E5 E8DE110000          <1> 	call	iclose ; close if it is special file 
  3497                              <1> 		; jsr r0,iclose / check to see if its a special file
  3498                              <1> fclose_2: ; 1:
  3499                              <1> 	; 24/12/2021
  3500 000041EA 58                  <1> 	pop	eax ; ***
  3501                              <1> 	;pop	ax ; ***
  3502                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3503 000041EB C3                  <1> 	retn
  3504                              <1> 		; rts r0
  3505                              <1> 
  3506                              <1> 	; 09/01/2022
  3507                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1. - Kernel v0.2.1.2)
  3508                              <1> getf:	; / get the device number and the i-number of an open file
  3509                              <1> 	; 13/05/2015
  3510                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3511                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3512                              <1> 	;
  3513 000041EC 89C3                <1> 	mov	ebx, eax
  3514                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3515                              <1> 	; 08/01/2022
  3516 000041EE 29C0                <1> 	sub	eax, eax
  3517                              <1> 	;
  3518 000041F0 83FB0A              <1> 	cmp	ebx, 10
  3519                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3520 000041F3 7329                <1>         jnb	short getf2 ; 13/05/2015
  3521                              <1> 	;jnb	error
  3522                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3523                              <1> 			    ; / index in fsp table
  3524                              <1> 	; 08/01/2022
  3525 000041F5 8A83[9E680000]      <1> 	mov	al, [ebx+u.fp]
  3526                              <1> 	;mov	bl, [ebx+u.fp]
  3527                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3528                              <1> 		                  ; / in fsp table
  3529                              <1> 	; 08/01/2022
  3530 000041FB 08C0                <1> 	or	al, al
  3531 000041FD 741F                <1> 	jz	short getf2	
  3532                              <1> 	;or	bl, bl
  3533                              <1> 	;jnz	short getf3
  3534                              <1> 	;;jz	short getf4
  3535                              <1> 		; beq 1f / if its zero return
  3536                              <1> ;getf2:
  3537                              <1> ;	; 08/01/2022
  3538                              <1> ;	; 'File not open !' error (ax=0)
  3539                              <1> ;	;sub	eax, eax
  3540                              <1> ;	retn
  3541                              <1> 
  3542                              <1> getf3:	
  3543                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3544                              <1> 	;
  3545                              <1> 	; 'fsp' table (10 bytes/entry)
  3546                              <1> 	; bit 15				   bit 0
  3547                              <1> 	; ---|-------------------------------------------
  3548                              <1> 	; r/w|		i-number of open file
  3549                              <1> 	; ---|-------------------------------------------
  3550                              <1> 	;		   device number
  3551                              <1> 	; -----------------------------------------------
  3552                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3553                              <1> 	; -----------------------------------------------
  3554                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3555                              <1> 	; ----------------------|------------------------
  3556                              <1> 	;  flag that says file 	| number of processes
  3557                              <1> 	;   has been deleted	| that have file open 
  3558                              <1> 	; ----------------------|------------------------
  3559                              <1> 	;
  3560                              <1> 	;mov	eax, 10
  3561                              <1> 	; 08/01/2022
  3562 000041FF B30A                <1> 	mov	bl, 10
  3563 00004201 F6E3                <1> 	mul	bl
  3564 00004203 BB[5E660000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3565 00004208 01C3                <1> 	add	ebx, eax
  3566                              <1> 		; asl r1
  3567                              <1> 		; asl r1 / multiply by 8 to get index into 
  3568                              <1> 		       ; / fsp table entry
  3569                              <1> 		; asl r1
  3570                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3571                              <1> 			      ; / in the fsp entry
  3572 0000420A 891D[A8680000]      <1> 	mov	[u.fofp], ebx
  3573                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3574                              <1> 			      ; / in fsp entry in u.fofp
  3575 00004210 4B                  <1> 	dec	ebx
  3576 00004211 4B                  <1> 	dec	ebx
  3577                              <1> 	;mov	ax, [ebx]
  3578                              <1> 	; 09/01/2022
  3579 00004212 8A03                <1> 	mov	al, [ebx]
  3580 00004214 A2[7B680000]        <1> 	mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3581                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3582                              <1> 			     ;;dev number is in 1 byte
  3583                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3584 00004219 4B                  <1> 	dec	ebx
  3585 0000421A 4B                  <1> 	dec	ebx
  3586 0000421B 668B03              <1> 	mov	ax, [ebx]
  3587                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3588                              <1> getf2:	; 08/01/2022
  3589                              <1> getf4:	; 1:
  3590 0000421E C3                  <1> 	retn
  3591                              <1> 		; rts r0
  3592                              <1> 
  3593                              <1> namei:
  3594                              <1> 	; 15/05/2022 (mounted directory path, '..' method)
  3595                              <1> 	; 03/02/2022
  3596                              <1> 	; 09/01/2022
  3597                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3598                              <1> 	; 04/12/2015 (Retro UNIX 386 v1.1, 14 byte file names)
  3599                              <1> 	; 18/10/2015 (nbase, ncount)
  3600                              <1> 	; 12/10/2015
  3601                              <1> 	; 21/08/2015
  3602                              <1> 	; 18/07/2015
  3603                              <1> 	; 02/07/2015
  3604                              <1> 	; 17/06/2015
  3605                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3606                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3607                              <1> 	;
  3608                              <1> 	; 'namei' takes a file path name and returns i-number of
  3609                              <1> 	; the file in the current directory or the root directory
  3610                              <1> 	; (if the first character of the pathname is '/').	
  3611                              <1> 	;
  3612                              <1> 	; INPUTS ->
  3613                              <1> 	;    u.namep - points to a file path name
  3614                              <1> 	;    u.cdir - i-number of users directory
  3615                              <1> 	;    u.cdev - device number on which user directory resides	
  3616                              <1> 	; OUTPUTS ->
  3617                              <1> 	;    r1 - i-number of file
  3618                              <1> 	;    cdev
  3619                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3620                              <1> 	;               occurs in the search for file path name.
  3621                              <1> 	;	        If no match u.dirb points to the end of 
  3622                              <1> 	;               the directory and r1 = i-number of the current
  3623                              <1> 	;	        directory.	
  3624                              <1> 	; ((AX = R1))
  3625                              <1> 	;
  3626                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3627                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3628                              <1> 	;
  3629                              <1> 
  3630 0000421F 66A1[9C680000]      <1> 	mov	ax, [u.cdir]
  3631                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3632                              <1> 			      ; / in r1
  3633                              <1> 	; 09/01/2022
  3634 00004225 8A15[E2680000]      <1> 	mov	dl, [u.cdrv]
  3635 0000422B 8815[7B680000]      <1> 	mov	[cdev], dl
  3636                              <1> 	;mov	dx, [u.cdrv]
  3637                              <1> 	;mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3638                              <1> 				    ; device/drive number is in 1 byte, 
  3639                              <1> 				    ; not in 1 word!
  3640                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3641                              <1> 				; / into cdev
  3642                              <1> 	; 12/10/2015
  3643                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3644                              <1>       	 ; convert virtual (pathname) addr to physical address
  3645 00004231 E868010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3646                              <1> 		; esi = physical address of [u.namep]
  3647                              <1> 		; ecx = byte count in the page
  3648 00004236 803E2F              <1> 	cmp	byte [esi], '/'
  3649                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3650 00004239 751D                <1> 	jne	short namei_1
  3651                              <1> 		; bne 1f
  3652 0000423B FF05[B0680000]      <1> 	inc	dword [u.namep]
  3653                              <1> 		; inc u.namep / go to next char
  3654                              <1> 	;dec	cx ; remain byte count in the page
  3655                              <1> 	; 24/12/2021
  3656 00004241 49                  <1> 	dec	ecx
  3657 00004242 7506                <1> 	jnz	short namei_0
  3658                              <1> 	; 12/10/2015
  3659 00004244 E855010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3660                              <1> 		; esi = physical address (page start + offset)
  3661                              <1> 		; ecx = byte count in the page
  3662 00004249 4E                  <1> 	dec	esi
  3663                              <1> namei_0:
  3664 0000424A 46                  <1> 	inc 	esi  ; go to next char
  3665 0000424B 66A1[86680000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3666                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3667 00004251 C605[7B680000]00    <1> 	mov	byte [cdev], 0
  3668                              <1> 		; clr cdev / clear device number
  3669                              <1> namei_1: ; 1:
  3670 00004258 F606FF              <1> 	test	byte [esi], 0FFh
  3671                              <1> namei_10: ; 24/12/2021 (jump from namei_8)
  3672 0000425B 74C1                <1> 	jz	short getf4
  3673                              <1> 	;jz	nig
  3674                              <1> 		; tstb *u.namep / is the character in file name a nul
  3675                              <1> 		; beq nig / yes, end of file name reached; 
  3676                              <1> 			; / branch to "nig"
  3677                              <1> namei_2: ; 1:
  3678                              <1> 	; 18/10/2015
  3679 0000425D 8935[10690000]      <1> 	mov 	[nbase], esi
  3680 00004263 66890D[14690000]    <1> 	mov 	[ncount], cx
  3681                              <1> 	;
  3682                              <1> 	;mov	dx, 2
  3683 0000426A B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3684 0000426C E892080000          <1> 	call	access
  3685                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3686                              <1> 	; 'access' will not return here if user has not "r" permission !
  3687                              <1> 	; 03/02/2022
  3688 00004271 F605[95650000]40    <1> 	test	byte [i.flgs+1], 40h
  3689                              <1> 	;test 	word [i.flgs], 4000h
  3690                              <1> 		; bit $40000,i.flgs / directory i-node?
  3691 00004278 746A                <1>         jz      short namei_err
  3692                              <1> 		; beq error3 / no, got an error
  3693                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3694 0000427A 31C0                <1> 	xor	eax, eax
  3695 0000427C A3[B4680000]        <1> 	mov	[u.off], eax ; 0
  3696 00004281 66A1[98650000]      <1> 	mov	ax, [i.size]
  3697 00004287 A3[AC680000]        <1> 	mov	[u.dirp], eax
  3698                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3699                              <1> 		; clr u.off / u.off is file offset used by user
  3700 0000428C C705[A8680000]-     <1> 	mov	dword [u.fofp], u.off
  3700 00004292 [B4680000]          <1>
  3701                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3702                              <1> 				  ; / the offset portion of fsp entry
  3703                              <1> namei_3: ; 2:
  3704 00004296 C705[B8680000]-     <1> 	mov	dword [u.base], u.dirbuf
  3704 0000429C [CA680000]          <1>
  3705                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3706                              <1> 				    ; / copied from a directory
  3707 000042A0 C705[BC680000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3707 000042A8 0000                <1>
  3708                              <1>  		; mov $10.,u.count / u.count is byte count 
  3709                              <1> 				 ; / for reads and writes
  3710 000042AA 66A1[78680000]      <1> 	mov 	ax, [ii]
  3711                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3712 000042B0 FE05[FF680000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3713 000042B6 E848090000          <1>     	call	readi
  3714                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3715                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3716 000042BB 8B0D[C0680000]      <1> 	mov 	ecx, [u.nread]
  3717 000042C1 09C9                <1> 	or 	ecx, ecx
  3718                              <1> 		; tst u.nread
  3719 000042C3 741B                <1> 	jz	short nib
  3720                              <1> 		; ble nib / gives error return
  3721                              <1> 	;
  3722 000042C5 668B1D[CA680000]    <1> 	mov 	bx, [u.dirbuf]
  3723 000042CC 6621DB              <1> 	and 	bx, bx       
  3724                              <1> 		; tst u.dirbuf /
  3725 000042CF 7522                <1> 	jnz	short namei_4
  3726                              <1> 		; bne 3f / branch when active directory entry 
  3727                              <1> 		       ; / (i-node word in entry non zero)
  3728 000042D1 A1[B4680000]        <1> 	mov	eax, [u.off]
  3729 000042D6 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3730 000042D9 A3[AC680000]        <1> 	mov	[u.dirp], eax
  3731                              <1> 		; mov u.off,u.dirp
  3732                              <1> 		; sub $10.,u.dirp
  3733 000042DE EBB6                <1> 	jmp	short namei_3
  3734                              <1> 		; br 2b
  3735                              <1> 
  3736                              <1> 	; 18/07/2013
  3737                              <1> nib: 
  3738 000042E0 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3739 000042E2 F9                  <1> 	stc
  3740                              <1> nig:
  3741 000042E3 C3                  <1> 	retn
  3742                              <1> 
  3743                              <1> namei_err:
  3744                              <1> 	; 16/06/2015
  3745 000042E4 C705[ED680000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3745 000042EC 0000                <1>
  3746 000042EE E91FF0FFFF          <1> 	jmp	error
  3747                              <1> 
  3748                              <1> namei_4: ; 3:
  3749                              <1> 	; 18/10/2015
  3750                              <1> 	; 12/10/2015
  3751                              <1> 	; 21/08/2015
  3752                              <1> 	; 18/07/2015
  3753 000042F3 8B2D[B0680000]      <1> 	mov	ebp, [u.namep]
  3754                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3755 000042F9 BF[CC680000]        <1> 	mov 	edi, u.dirbuf + 2
  3756                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3757                              <1> 	; 18/10/2015
  3758 000042FE 8B35[10690000]      <1> 	mov	esi, [nbase]	
  3759 00004304 668B0D[14690000]    <1> 	mov	cx, [ncount]
  3760                              <1> 	;
  3761 0000430B 6621C9              <1> 	and	cx, cx
  3762 0000430E 7505                <1> 	jnz	short namei_5	
  3763                              <1> 	;
  3764 00004310 E88F000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3765                              <1> 		; esi = physical address (page start + offset)
  3766                              <1> 		; ecx = byte count in the page
  3767                              <1> namei_5: ; 3:
  3768 00004315 45                  <1> 	inc	ebp ; 18/07/2015
  3769 00004316 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3770                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3771 00004317 08C0                <1> 	or 	al, al
  3772 00004319 741C                <1> 	jz 	short namei_7
  3773                              <1> 		; beq 3f / if char is nul, then the last char in string
  3774                              <1> 			; / has been moved
  3775 0000431B 3C2F                <1> 	cmp	al, '/'
  3776                              <1> 		; cmp r4,$'/ / is char a </>
  3777 0000431D 7418                <1> 	je 	short namei_7
  3778                              <1> 		; beq 3f	
  3779                              <1> 	; 24/12/2021
  3780 0000431F 49                  <1> 	dec	ecx
  3781                              <1> 	; 12/10/2015
  3782                              <1> 	;dec	cx ; remain byte count in the page
  3783 00004320 7505                <1> 	jnz	short namei_6
  3784 00004322 E87D000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3785                              <1> 		; esi = physical address (page start + offset)
  3786                              <1> 		; ecx = byte count in the page
  3787                              <1> namei_6:
  3788 00004327 81FF[DA680000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3789                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3790                              <1> 				     ; / all 8 bytes of file name
  3791 0000432D 74E6                <1> 	je	short namei_5
  3792                              <1> 		; beq 3b
  3793 0000432F AE                  <1> 	scasb	
  3794                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3795                              <1> 			      ; / char read from directory
  3796 00004330 74E3                <1> 	je 	short namei_5
  3797                              <1> 		; beq 3b / branch if chars match
  3798                              <1> namei_9:
  3799 00004332 E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3800                              <1> 		; br 2b / file names do not match go to next directory entry
  3801                              <1> namei_7: ; 3:
  3802 00004337 81FF[DA680000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3803                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3804 0000433D 7406                <1> 	je	short namei_8
  3805                              <1> 		; beq 3f
  3806 0000433F 8A27                <1> 	mov 	ah, [edi]
  3807                              <1> 	;inc 	edi 
  3808 00004341 20E4                <1> 	and 	ah, ah
  3809                              <1> 		; tstb (r3)+ /
  3810                              <1>         ;jnz	namei_3
  3811                              <1> 		; bne 2b
  3812                              <1> 	; 24/12/2021
  3813 00004343 75ED                <1> 	jnz	short namei_9	
  3814                              <1> namei_8: ; 3
  3815 00004345 892D[B0680000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3816                              <1> 		; mov r2,u.namep / u.namep points to char 
  3817                              <1> 			       ; / following a / or nul
  3818                              <1> 	;mov	bx, [u.dirbuf]
  3819                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3820                              <1> 				; / entry to r1
  3821                              <1> 	;;;;
  3822                              <1> 	; 15/05/2022 - Retro UNIX (8086/386) feature only !
  3823                              <1> 	; ! 'pwd' utility modification !
  3824                              <1> 	; ((if directory entry name is a dotdot)))
  3825                              <1> 	;; check if it is mounted device's root directory inode
  3826                              <1> 	; and if so, replace it with parent dir inode number
  3827                              <1> 	;  of mounting directory in [mntp].
  3828                              <1> 
  3829 0000434B 668B1D[CA680000]    <1> 	mov	bx, [u.dirbuf]
  3830                              <1> 
  3831 00004352 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3832 00004356 753C                <1> 	jne	short namei_11
  3833                              <1> 
  3834 00004358 663B1D[78680000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3835 0000435F 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3836                              <1> 
  3837                              <1> 	;cmp	[idev], bh ; 0
  3838 00004361 383D[7B680000]      <1> 	cmp	[cdev], bh ; 0
  3839                              <1> 			; 0 = root fs, dev num in [rdev]
  3840                              <1> 			; 1 = mounted, dev num in [mdev]
  3841 00004367 762B                <1> 	jna	short namei_11
  3842                              <1> 
  3843                              <1> 	; dotdot (parent directory link) check
  3844 00004369 66813D[CC680000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3844 00004371 2E                  <1>
  3845 00004372 7520                <1> 	jne	short namei_11
  3846 00004374 803D[CE680000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3847 0000437B 7517                <1> 	jne	short namei_11
  3848                              <1> 	
  3849                              <1> 	; (This may not be necessary because [idev] = 1
  3850                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3851 0000437D 66391D[80680000]    <1> 	cmp	[mnti], bx ; 41
  3852 00004384 760E                <1> 	jna	short namei_11
  3853                              <1> 	
  3854                              <1> 	; change inumber to parent dir inum of mount directory
  3855 00004386 668B1D[82680000]    <1> 	mov	bx, [mntp]
  3856 0000438D C605[7B680000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3857                              <1> namei_11:
  3858                              <1> 	;;;;
  3859                              <1> 
  3860 00004394 20C0                <1> 	and 	al, al
  3861                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3862                              <1> 		      ;  / if r4 = </> then go to next directory
  3863                              <1> 	; 15/05/2022
  3864 00004396 6689D8              <1> 	mov	ax, bx
  3865                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3866                              <1>   	; 24/12/2021
  3867 00004399 E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3868                              <1> 	;jnz	namei_2 
  3869                              <1> 		; bne 1b
  3870                              <1> 	; AX = i-number of the file
  3871                              <1> ;;nig:
  3872                              <1> 	;retn	; 24/12/2021
  3873                              <1> 		; tst (r0)+ / gives non-error return
  3874                              <1> ;;nib:
  3875                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3876                              <1> 		       ; ax = 0 -> file not found 
  3877                              <1> ;;	stc	; 27/05/2013
  3878                              <1> ;;	retn
  3879                              <1> 		; rts r0
  3880                              <1> 
  3881                              <1> trans_addr_nmbp:
  3882                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3883                              <1> 	; 18/10/2015
  3884                              <1> 	; 12/10/2015
  3885 0000439E 8B2D[B0680000]      <1> 	mov 	ebp, [u.namep]
  3886                              <1> trans_addr_nm:
  3887                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 
  3888                              <1> 	; Convert virtual (pathname) address to physical address
  3889                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3890                              <1> 	; 18/10/2015
  3891                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3892                              <1> 	; 02/07/2015
  3893                              <1> 	; 17/06/2015
  3894                              <1> 	; 16/06/2015
  3895                              <1> 	;
  3896                              <1> 	; INPUTS: 
  3897                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3898                              <1> 	;	[u.pgdir] = user's page directory
  3899                              <1> 	; OUTPUT:
  3900                              <1> 	;       esi = physical address of the pathname
  3901                              <1> 	;	ecx = remain byte count in the page
  3902                              <1> 	;
  3903                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3904                              <1> 	;
  3905                              <1> 
  3906                              <1> 	; 08/01/2022
  3907 000043A4 29C9                <1> 	sub	ecx, ecx
  3908                              <1> 	;
  3909 000043A6 833D[F5680000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3910 000043AD 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3911                              <1> 				     ; it is already physical address
  3912 000043AF 50                  <1>    	push	eax	
  3913 000043B0 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3914 000043B2 E836E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3915 000043B7 7204                <1> 	jc	short tr_addr_nm_err
  3916                              <1> 	; 18/10/2015
  3917                              <1> 	; eax = physical address 
  3918                              <1> 	; cx = remain byte count in page (1-4096) 
  3919                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3920 000043B9 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3921 000043BB 58                  <1> 	pop	eax 
  3922 000043BC C3                  <1> 	retn
  3923                              <1> 
  3924                              <1> tr_addr_nm_err:
  3925 000043BD A3[ED680000]        <1> 	mov	[u.error], eax
  3926                              <1> 	;pop 	eax
  3927 000043C2 E94BEFFFFF          <1> 	jmp	error
  3928                              <1> 
  3929                              <1> trans_addr_nmk:
  3930                              <1> 	; 12/10/2015
  3931                              <1> 	; 02/07/2015
  3932 000043C7 8B35[B0680000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3933                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3934                              <1> 	; 08/01/2022
  3935 000043CD B510                <1> 	mov	ch, PAGE_SIZE/256
  3936 000043CF C3                  <1> 	retn
  3937                              <1> 
  3938                              <1> syschdir:
  3939                              <1> 	; / makes the directory specified in the argument
  3940                              <1> 	; / the current directory
  3941                              <1> 	;
  3942                              <1> 	; 09/01/2022
  3943                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3944                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3945                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3946                              <1> 	;
  3947                              <1> 	; 'syschdir' makes the directory specified in its argument
  3948                              <1> 	; the current working directory.
  3949                              <1> 	;
  3950                              <1> 	; Calling sequence:
  3951                              <1> 	;	syschdir; name
  3952                              <1> 	; Arguments:
  3953                              <1> 	;	name - address of the path name of a directory
  3954                              <1> 	;	       terminated by nul byte.	
  3955                              <1> 	; Inputs: -
  3956                              <1> 	; Outputs: -
  3957                              <1> 	; ...............................................................
  3958                              <1> 	;				
  3959                              <1> 	; Retro UNIX 8086 v1 modification:
  3960                              <1> 	;	 The user/application program puts address of 
  3961                              <1> 	;	 the path name in BX register as 'syschdir' 
  3962                              <1> 	; 	 system call argument.
  3963                              <1> 
  3964 000043D0 891D[B0680000]      <1> 	mov	[u.namep], ebx
  3965                              <1> 		; jsr r0,arg; u.namep / u.namep points to path name
  3966 000043D6 E844FEFFFF          <1> 	call	namei
  3967                              <1> 		; jsr r0,namei / find its i-number
  3968                              <1> 	;jc	error
  3969                              <1> 		; br error3
  3970 000043DB 730F                <1> 	jnc	short syschdir0
  3971                              <1> 	; 'directory not found !' error
  3972 000043DD C705[ED680000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3972 000043E5 0000                <1>
  3973 000043E7 E926EFFFFF          <1> 	jmp	error
  3974                              <1> syschdir0:
  3975                              <1> 	; 08/01/2022
  3976 000043EC B202                <1> 	mov	dl, 2  ; read access ; 08/01/2022 (BugFix)
  3977 000043EE E810070000          <1> 	call	access
  3978                              <1> 		; jsr r0,access; 2 / get i-node into core
  3979                              <1> 	; 08/01/2022
  3980 000043F3 F605[95650000]40    <1> 	test	byte [i.flgs+1], 40h
  3981                              <1> 	;test	word [i.flgs], 4000h
  3982                              <1> 		; bit $40000,i.flgs / is it a directory?
  3983                              <1> 	;jz	error 
  3984                              <1> 		; beq error3 / no error
  3985 000043FA 750F                <1> 	jnz	short syschdir1
  3986 000043FC C705[ED680000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3986 00004404 0000                <1>
  3987 00004406 E907EFFFFF          <1> 	jmp	error
  3988                              <1> syschdir1:
  3989 0000440B 66A3[9C680000]      <1> 	mov	[u.cdir], ax
  3990                              <1> 		; mov r1,u.cdir / move i-number to users 
  3991                              <1> 			      ; / current directory
  3992                              <1> 	; 09/01/2022
  3993 00004411 A0[7B680000]        <1> 	mov	al, [cdev]
  3994 00004416 A2[E2680000]        <1> 	mov	[u.cdrv], al
  3995                              <1> 	;mov	ax, [cdev]
  3996                              <1> 	;mov	[u.cdrv], ax
  3997                              <1> 		; mov cdev,u.cdev / move its device to users 
  3998                              <1> 			        ; / current device
  3999 0000441B E912EFFFFF          <1> 	jmp	sysret
  4000                              <1> 		; br sysret3
  4001                              <1> 
  4002                              <1> syschmod: ; < change mode of file >
  4003                              <1> 	; 29/04/2022 (bugfix)
  4004                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4005                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4006                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4007                              <1> 	;
  4008                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4009                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4010                              <1> 	; changed to 'mode'.
  4011                              <1> 	;
  4012                              <1> 	; Calling sequence:
  4013                              <1> 	;	syschmod; name; mode
  4014                              <1> 	; Arguments:
  4015                              <1> 	;	name - address of the file name
  4016                              <1> 	;	       terminated by null byte.
  4017                              <1> 	;	mode - (new) mode/flags < attributes >
  4018                              <1> 	;	
  4019                              <1> 	; Inputs: -
  4020                              <1> 	; Outputs: -
  4021                              <1> 	; ...............................................................
  4022                              <1> 	;				
  4023                              <1> 	; Retro UNIX 8086 v1 modification: 
  4024                              <1> 	;       'syschmod' system call has two arguments; so,
  4025                              <1> 	;	* 1st argument, name is pointed to by BX register
  4026                              <1> 	;	* 2nd argument, mode is in CX register
  4027                              <1> 	;
  4028                              <1> 	; Mode bits (Flags):
  4029                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  4030                              <1> 	;	bit 14 - directory flag (4000h)
  4031                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  4032                              <1> 	;	bit 12 - large file flag (1000h)
  4033                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4034                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  4035                              <1> 	;	bit 4 - executable flag (10h)
  4036                              <1> 	;	bit 3 - read permission for owner (08h)
  4037                              <1> 	;	bit 2 - write permission for owner (04h)
  4038                              <1> 	;	bit 1 - read permission for non-owner (02h)
  4039                              <1> 	;	bit 0 - write permission for non-owner (01h)
  4040                              <1> 
  4041                              <1> 	; / name; mode
  4042 00004420 E815000000          <1> 	call	isown
  4043                              <1> 		;jsr r0,isown / get the i-node and check user status
  4044                              <1> 	; 09/01/2022
  4045 00004425 F605[95650000]40    <1> 	test	byte [i.flgs+1], 40h
  4046                              <1> 	;test	word [i.flgs], 4000h
  4047                              <1> 		; bit $40000,i.flgs / directory?
  4048 0000442C 7402                <1> 	jz	short syschmod1
  4049                              <1> 		; beq 2f / no
  4050                              <1> 	; AL = (new) mode
  4051 0000442E 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4052                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  4053                              <1> 			   ; / executable modes
  4054                              <1> syschmod1: ; 2:
  4055 00004430 A2[94650000]        <1> 	mov	[i.flgs], al	
  4056                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  4057                              <1> 	;jmp	short isown1
  4058                              <1> 	;	; br 1f ; (jmp sysret4)
  4059                              <1> 	; 29/04/2022
  4060 00004435 E9F8EEFFFF          <1> 	jmp	sysret
  4061                              <1> 
  4062                              <1> isown:
  4063                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4064                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4065                              <1> 	;
  4066                              <1> 	; 'isown' is given a file name (the 1st argument).
  4067                              <1> 	;  It find the i-number of that file via 'namei' 
  4068                              <1> 	;  then gets the i-node into core via 'iget'.
  4069                              <1> 	;  It then tests to see if the user is super user. 
  4070                              <1> 	;  If not, it cheks to see if the user is owner of 
  4071                              <1> 	;  the file. If he is not an error occurs.
  4072                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4073                              <1> 	;  the inode has been modified and the 2nd argument of
  4074                              <1> 	;  the call is put in r2.
  4075                              <1> 	;
  4076                              <1> 	; INPUTS ->
  4077                              <1> 	;    arguments of syschmod and syschown calls
  4078                              <1> 	; OUTPUTS ->
  4079                              <1> 	;    u.uid - id of user
  4080                              <1> 	;    imod - set to a 1
  4081                              <1> 	;    r2 - contains second argument of the system call				 	
  4082                              <1> 	;
  4083                              <1> 	;   ((AX=R2) output as 2nd argument)
  4084                              <1> 	;
  4085                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4086                              <1> 	;
  4087                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4088                              <1> 	;; ! 2nd argument on top of stack !
  4089                              <1> 	;; 22/06/2015 - 32 bit modifications
  4090                              <1> 	;; 07/07/2013
  4091 0000443A 891D[B0680000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4092 00004440 51                  <1> 	push 	ecx ;; 2nd argument
  4093                              <1> 	;;
  4094 00004441 E8D9FDFFFF          <1> 	call	namei
  4095                              <1> 		; jsr r0,namei / get its i-number
  4096                              <1>        ; Retro UNIX 8086 v1 modification !
  4097                              <1>        ; ax = 0 -> file not found 
  4098                              <1> 	;and	ax, ax
  4099                              <1> 	;jz	error
  4100                              <1> 	;jc	error ; 27/05/2013
  4101                              <1> 		; br error3
  4102 00004446 730F                <1> 	jnc	short isown0
  4103                              <1> 	; 'file not found !' error
  4104 00004448 C705[ED680000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4104 00004450 0000                <1>
  4105 00004452 E9BBEEFFFF          <1> 	jmp	error
  4106                              <1> isown0:
  4107 00004457 E8D3050000          <1> 	call	iget
  4108                              <1> 		; jsr r0,iget / get i-node into core
  4109 0000445C A0[E4680000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4110 00004461 08C0                <1> 	or	al, al
  4111                              <1> 		; tstb u.uid / super user?
  4112 00004463 7417                <1> 	jz	short isown1
  4113                              <1> 		; beq 1f / yes, branch
  4114 00004465 3A05[97650000]      <1> 	cmp	al, [i.uid]
  4115                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4116                              <1> 				 ; / the file
  4117                              <1> 	;jne	error
  4118                              <1> 		; beq 1f / yes
  4119                              <1> 		; jmp error3 / no, error
  4120 0000446B 740F                <1> 	je	short isown1
  4121                              <1> 
  4122 0000446D C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4122 00004475 0000                <1>
  4123                              <1> 			;  'permission denied !' error
  4124 00004477 E996EEFFFF          <1> 	jmp	error
  4125                              <1> isown1: ; 1:
  4126 0000447C E8B8060000          <1> 	call	setimod
  4127                              <1> 		; jsr r0,setimod / indicates 
  4128                              <1> 		;	       ; / i-node has been modified
  4129 00004481 58                  <1> 	pop	eax ; 2nd argument
  4130                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4131                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4132 00004482 C3                  <1> 	retn
  4133                              <1> 		; rts r0
  4134                              <1> 
  4135                              <1> ;;arg:  ; < get system call arguments >
  4136                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4137                              <1> 	; of form:
  4138                              <1> 	;	sys 'routine' ; arg1
  4139                              <1> 	;		or
  4140                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4141                              <1> 	;		or
  4142                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4143                              <1> 	;	
  4144                              <1> 	; INPUTS ->
  4145                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4146                              <1> 	;	This pointers's value is actually the value of
  4147                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4148                              <1> 	;	made to process the sys instruction
  4149                              <1> 	;    r0 - contains the return address for the routine
  4150                              <1> 	;	that called arg. The data in the word pointer 
  4151                              <1> 	;	to by the return address is used as address
  4152                              <1> 	;	in which the extracted argument is stored   		
  4153                              <1> 	;    	
  4154                              <1> 	; OUTPUTS ->
  4155                              <1> 	;    'address' - contains the extracted argument 
  4156                              <1> 	;    u.sp+18 - is incremented by 2 
  4157                              <1> 	;    r1 - contains the extracted argument
  4158                              <1> 	;    r0 - points to the next instruction to be
  4159                              <1> 	;	 executed in the calling routine.
  4160                              <1> 	;
  4161                              <1>   
  4162                              <1> 	; mov u.sp,r1
  4163                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4164                              <1> 			; / into argument of arg2
  4165                              <1> 	; add $2,18.(r1) / point pc on stack 
  4166                              <1> 			      ; / to next system argument
  4167                              <1> 	; rts r0
  4168                              <1> 
  4169                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4170                              <1> 	; 'arg2' takes first argument in system call
  4171                              <1> 	;  (pointer to name of the file) and puts it in location
  4172                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4173                              <1> 	;  and on top of the stack
  4174                              <1> 	;	
  4175                              <1> 	; INPUTS ->
  4176                              <1> 	;    u.sp, r0
  4177                              <1> 	;    	
  4178                              <1> 	; OUTPUTS ->
  4179                              <1> 	;    u.namep
  4180                              <1> 	;    u.off 
  4181                              <1> 	;    u.off pushed on stack
  4182                              <1> 	;    r1
  4183                              <1> 	;
  4184                              <1> 
  4185                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4186                              <1> 				; / first arg in sys call
  4187                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4188                              <1> 				; / second arg in sys call
  4189                              <1> 	; mov r0,r1 / r0 points to calling routine
  4190                              <1> 	; mov (sp),r0 / put operation code back in r0
  4191                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4192                              <1> 			; / on stack
  4193                              <1> 	; jmp (r1) / return to calling routine
  4194                              <1> 
  4195                              <1> syschown: ; < change owner of file >
  4196                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4197                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4198                              <1> 	;
  4199                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4200                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4201                              <1> 	; changed to 'owner'
  4202                              <1> 	;
  4203                              <1> 	; Calling sequence:
  4204                              <1> 	;	syschown; name; owner
  4205                              <1> 	; Arguments:
  4206                              <1> 	;	name - address of the file name
  4207                              <1> 	;	       terminated by null byte.
  4208                              <1> 	;	owner - (new) owner (number/ID)
  4209                              <1> 	;	
  4210                              <1> 	; Inputs: -
  4211                              <1> 	; Outputs: -
  4212                              <1> 	; ...............................................................
  4213                              <1> 	;				
  4214                              <1> 	; Retro UNIX 8086 v1 modification: 
  4215                              <1> 	;       'syschown' system call has two arguments; so,
  4216                              <1> 	;	* 1st argument, name is pointed to by BX register
  4217                              <1> 	;	* 2nd argument, owner number is in CX register
  4218                              <1> 	;
  4219                              <1> 	; / name; owner
  4220 00004483 E8B2FFFFFF          <1> 	call	isown
  4221                              <1> 		; jsr r0,isown / get the i-node and check user status
  4222 00004488 803D[E4680000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4223                              <1> 		; tstb u.uid / super user
  4224 0000448F 7418                <1> 	jz	short syschown1
  4225                              <1> 		; beq 2f / yes, 2f
  4226 00004491 F605[94650000]20    <1>         test    byte [i.flgs], 20h ; 32
  4227                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4228                              <1> 	;jnz	error
  4229                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4230 00004498 740F                <1> 	jz	short syschown1
  4231                              <1> 	; 'permission denied !'
  4232 0000449A C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4232 000044A2 0000                <1>
  4233 000044A4 E969EEFFFF          <1> 	jmp	error
  4234                              <1> syschown1: ; 2:
  4235                              <1> 	; AL = owner (number/ID)
  4236 000044A9 A2[97650000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4237                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4238                              <1> 			       ; / in the i-node
  4239 000044AE E97FEEFFFF          <1> 	jmp	sysret
  4240                              <1> 	; 1: 
  4241                              <1> 		; jmp sysret4
  4242                              <1> 	; 3:
  4243                              <1> 		; jmp	error
  4244                              <1> 
  4245                              <1> systime: ; / get time of year
  4246                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4247                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4248                              <1> 	;
  4249                              <1> 	; 20/06/2013
  4250                              <1> 	; 'systime' gets the time of the year.
  4251                              <1> 	; The present time is put on the stack.
  4252                              <1> 	;
  4253                              <1> 	; Calling sequence:
  4254                              <1> 	;	systime
  4255                              <1> 	; Arguments: -
  4256                              <1> 	;	
  4257                              <1> 	; Inputs: -
  4258                              <1> 	; Outputs: sp+2, sp+4 - present time
  4259                              <1> 	; ...............................................................
  4260                              <1> 	;	
  4261                              <1> 	; Retro UNIX 8086 v1 modification: 
  4262                              <1> 	;       'systime' system call will return to the user
  4263                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4264                              <1> 	;
  4265                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4266                              <1> 	;	system call for PC compatibility !!		 	
  4267                              <1> 
  4268 000044B3 E8A8E9FFFF          <1> 	call 	epoch
  4269 000044B8 A3[98680000]        <1> 	mov 	[u.r0], eax
  4270                              <1> 		; mov s.time,4(sp)
  4271                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4272                              <1> 				   ; / on the stack
  4273                              <1> 		; br sysret4
  4274 000044BD E970EEFFFF          <1> 	jmp	sysret 
  4275                              <1> 
  4276                              <1> sysstime: ; / set time
  4277                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4278                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4279                              <1> 	;
  4280                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4281                              <1> 	;
  4282                              <1> 	; Calling sequence:
  4283                              <1> 	;	sysstime
  4284                              <1> 	; Arguments: -
  4285                              <1> 	;	
  4286                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4287                              <1> 	; Outputs: -
  4288                              <1> 	; ...............................................................
  4289                              <1> 	;	
  4290                              <1> 	; Retro UNIX 8086 v1 modification: 
  4291                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4292                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4293                              <1> 	; 
  4294                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4295                              <1> 	;	to get sysstime system call arguments from the user;
  4296                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4297                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4298                              <1> 	;
  4299                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4300                              <1> 	;	system call for PC compatibility !!	
  4301                              <1> 
  4302 000044C2 803D[E4680000]00    <1> 	cmp	byte [u.uid], 0
  4303                              <1> 		; tstb u.uid / is user the super user
  4304                              <1> 	;ja	error
  4305                              <1> 		; bne error4 / no, error
  4306 000044C9 760F                <1> 	jna	short systime1
  4307                              <1> 	; 'permission denied !'
  4308 000044CB C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4308 000044D3 0000                <1>
  4309 000044D5 E938EEFFFF          <1> 	jmp	error
  4310                              <1> systime1:
  4311                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4312                              <1> 	; EBX = unix (epoch) time (from user)
  4313 000044DA 89D8                <1> 	mov	eax, ebx
  4314 000044DC E8FFEAFFFF          <1> 	call 	set_date_time
  4315                              <1> 		; mov 4(sp),s.time
  4316                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4317 000044E1 E94CEEFFFF          <1> 	jmp	sysret
  4318                              <1> 		; br sysret4
  4319                              <1> 
  4320                              <1> sysbreak:
  4321                              <1> 	; 18/10/2015
  4322                              <1> 	; 07/10/2015
  4323                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4324                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4325                              <1> 	;
  4326                              <1> 	; 'sysbreak' sets the programs break points. 
  4327                              <1> 	; It checks the current break point (u.break) to see if it is
  4328                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4329                              <1> 	; even address (if it was odd) and the area between u.break
  4330                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4331                              <1> 	; in u.break and control is passed to 'sysret'.
  4332                              <1> 	;
  4333                              <1> 	; Calling sequence:
  4334                              <1> 	;	sysbreak; addr
  4335                              <1> 	; Arguments: -
  4336                              <1> 	;	
  4337                              <1> 	; Inputs: u.break - current breakpoint
  4338                              <1> 	; Outputs: u.break - new breakpoint 
  4339                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4340                              <1> 	; ...............................................................
  4341                              <1> 	;	
  4342                              <1> 	; Retro UNIX 8086 v1 modification:
  4343                              <1> 	;	The user/application program puts breakpoint address
  4344                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4345                              <1> 	; 	(argument transfer method 1)
  4346                              <1> 	;
  4347                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4348                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4349                              <1> 	;  NOTE:
  4350                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4351                              <1> 	;	'u.break' address) of user's memory for original unix's
  4352                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4353                              <1> 
  4354                              <1> 		; mov u.break,r1 / move users break point to r1
  4355                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4356                              <1> 		; blos 1f / yes, 1f
  4357                              <1> 	; 23/06/2015
  4358 000044E6 8B2D[C4680000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4359                              <1> 	;and	ebp, ebp
  4360                              <1> 	;jz	short sysbreak_3 
  4361                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4362                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4363 000044EC 8B15[90680000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4364 000044F2 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4365                              <1> 	; 07/10/2015
  4366 000044F5 891D[C4680000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4367                              <1> 	;
  4368 000044FB 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4369                              <1> 			   ; with top of user's stack (virtual!)
  4370 000044FD 7327                <1> 	jnb	short sysbreak_3
  4371                              <1> 		; cmp r1,sp / is it the same or higher 
  4372                              <1> 			  ; / than the stack?
  4373                              <1> 		; bhis 1f / yes, 1f
  4374 000044FF 89DE                <1> 	mov	esi, ebx
  4375 00004501 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4376 00004503 7621                <1> 	jna	short sysbreak_3 
  4377                              <1> 	;push	ebx
  4378                              <1> sysbreak_1:
  4379 00004505 89EB                <1> 	mov	ebx, ebp  
  4380 00004507 E8E1E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4381 0000450C 0F82ABFEFFFF        <1> 	jc	tr_addr_nm_err
  4382                              <1> 	; 18/10/2015
  4383 00004512 89C7                <1> 	mov	edi, eax 
  4384 00004514 29C0                <1> 	sub	eax, eax ; 0
  4385                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4386 00004516 39CE                <1> 	cmp	esi, ecx
  4387 00004518 7302                <1> 	jnb	short sysbreak_2
  4388 0000451A 89F1                <1> 	mov	ecx, esi
  4389                              <1> sysbreak_2:
  4390 0000451C 29CE                <1> 	sub	esi, ecx
  4391 0000451E 01CD                <1> 	add	ebp, ecx
  4392 00004520 F3AA                <1> 	rep 	stosb
  4393 00004522 09F6                <1> 	or	esi, esi
  4394 00004524 75DF                <1> 	jnz	short sysbreak_1
  4395                              <1> 	;
  4396                              <1> 		; bit $1,r1 / is it an odd address
  4397                              <1> 		; beq 2f / no, its even
  4398                              <1> 		; clrb (r1)+ / yes, make it even
  4399                              <1> 	; 2: / clear area between the break point and the stack
  4400                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4401                              <1> 		; bhis 1f / yes, quit
  4402                              <1> 		; clr (r1)+ / clear word
  4403                              <1> 		; br 2b / go back
  4404                              <1> 	;pop	ebx
  4405                              <1> sysbreak_3: ; 1:
  4406                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4407                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4408                              <1> 			; / in u.break (set new break point)
  4409                              <1> 		; br sysret4 / br sysret
  4410 00004526 E907EEFFFF          <1> 	jmp	sysret
  4411                              <1> 
  4412                              <1> maknod: 
  4413                              <1> 	; 11/02/2022
  4414                              <1> 	; 09/01/2022
  4415                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4416                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4417                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4418                              <1> 	;
  4419                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4420                              <1> 	; for this i-node in the current directory.
  4421                              <1> 	;
  4422                              <1> 	; INPUTS ->
  4423                              <1> 	;    r1 - contains mode
  4424                              <1> 	;    ii - current directory's i-number	
  4425                              <1> 	;    	
  4426                              <1> 	; OUTPUTS ->
  4427                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4428                              <1> 	;    i.flgs - flags in new i-node 
  4429                              <1> 	;    i.uid - filled with u.uid
  4430                              <1> 	;    i.nlks - 1 is put in the number of links
  4431                              <1> 	;    i.ctim - creation time				
  4432                              <1> 	;    i.ctim+2 - modification time
  4433                              <1> 	;    imod - set via call to setimod
  4434                              <1> 	;	
  4435                              <1> 	; ((AX = R1)) input
  4436                              <1> 	;
  4437                              <1> 	; (Retro UNIX Prototype : 
  4438                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4439                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4440                              <1> 
  4441                              <1> 	; / r1 contains the mode
  4442 0000452B 80CC80              <1> 	or 	ah, 80h	; 10000000b
  4443                              <1> 		; bis $100000,r1 / allocate flag set
  4444 0000452E 6650                <1> 	push	ax ; * ; 24/12/2021
  4445                              <1> 		; mov r1,-(sp) / put mode on stack
  4446                              <1> 	; 31/07/2013
  4447 00004530 66A1[78680000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4448                              <1> 		; mov ii,r1 / move current i-number to r1
  4449 00004536 B201                <1> 	mov	dl, 1 ; owner flag mask
  4450 00004538 E8C6050000          <1> 	call	access	
  4451                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4452 0000453D 50                  <1> 	push	eax ; ** ; 24/12/2021
  4453                              <1> 		; mov r1,-(sp) / put i-number on stack
  4454 0000453E 66B82800            <1> 	mov	ax, 40
  4455                              <1> 		; mov $40.,r1 / r1 = 40
  4456                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4457 00004542 6640                <1> 	inc	ax
  4458                              <1> 		; inc r1 / r1 = r1 + 1
  4459 00004544 E87F060000          <1> 	call	imap
  4460                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4461                              <1> 			    ; /	inode map in r2 & m
  4462                              <1>   
  4463                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4464                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4465                              <1> 
  4466                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4467                              <1> 	;	       Inode count must be checked here
  4468                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4469                              <1> 
  4470                              <1> 	; 11/02/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  4471                              <1> 	; (inode count check)
  4472                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4473                              <1> 
  4474 00004549 730F                <1> 	jnc	short maknod2
  4475                              <1> 
  4476                              <1> 	; no free inode in inode table !
  4477 0000454B C705[ED680000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4477 00004553 0000                <1>
  4478                              <1> 			; miscellaneous/other errors
  4479 00004555 E9B8EDFFFF          <1> 	jmp	error	
  4480                              <1> maknod2: 
  4481 0000455A 8413                <1> 	test	[ebx], dl
  4482                              <1> 		; bitb mq,(r2) / is the i-node active
  4483 0000455C 75E4                <1> 	jnz	short maknod1
  4484                              <1> 		; bne 1b / yes, try the next one
  4485 0000455E 0813                <1> 	or	[ebx], dl
  4486                              <1> 		; bisb mq,(r2) / no, make it active 
  4487                              <1> 			     ; / (put a 1 in the bit map)
  4488 00004560 E8CA040000          <1> 	call	iget
  4489                              <1> 		; jsr r0,iget / get i-node into core
  4490                              <1> 	; 09/01/2022
  4491 00004565 F605[95650000]80    <1> 	test	byte [i.flgs+1], 80h
  4492                              <1> 	;test	word [i.flgs], 8000h 
  4493                              <1> 		; tst i.flgs / is i-node already allocated
  4494 0000456C 75D4                <1> 	jnz	short maknod1	
  4495                              <1> 		; blt 1b / yes, look for another one
  4496 0000456E 66A3[CA680000]      <1> 	mov	[u.dirbuf], ax
  4497                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4498 00004574 58                  <1> 	pop	eax ; ** ; 24/12/2021
  4499                              <1> 		; mov (sp)+,r1 / get current i-number back
  4500 00004575 E8B5040000          <1> 	call	iget
  4501                              <1> 		; jsr r0,iget / get i-node in core
  4502 0000457A E857F7FFFF          <1> 	call	mkdir
  4503                              <1> 		; jsr r0,mkdir / make a directory entry 
  4504                              <1> 			     ; / in current directory
  4505 0000457F 66A1[CA680000]      <1> 	mov	ax, [u.dirbuf]
  4506                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4507 00004585 E8A5040000          <1> 	call	iget
  4508                              <1> 		; jsr r0,iget / get it into core
  4509                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4510                              <1> 	;mov	ecx, 8
  4511                              <1> 	; 09/01/2022 
  4512 0000458A 29C9                <1> 	sub	ecx, ecx
  4513 0000458C B108                <1> 	mov	cl, 8
  4514 0000458E 31C0                <1> 	xor	eax, eax ; 0
  4515 00004590 BF[94650000]        <1> 	mov	edi, inode 
  4516 00004595 F3AB                <1> 	rep	stosd
  4517                              <1> 	;
  4518 00004597 668F05[94650000]    <1> 	pop	word [i.flgs] ; * ; 24/12/2021
  4519                              <1> 		; mov (sp)+,i.flgs / fill flags
  4520 0000459E 8A0D[E4680000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4521 000045A4 880D[97650000]      <1> 	mov 	[i.uid], cl
  4522                              <1> 		; movb u.uid,i.uid / user id	
  4523 000045AA C605[96650000]01    <1> 	mov     byte [i.nlks], 1
  4524                              <1> 		; movb $1,i.nlks / 1 link
  4525                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4526                              <1> 	;mov	eax, [s.time]
  4527                              <1> 	;mov 	[i.ctim], eax
  4528                              <1> 	 	; mov s.time,i.ctim / time created
  4529                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4530                              <1> 	; Retro UNIX 8086 v1 modification !
  4531                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4532                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4533                              <1> 	;call	setimod
  4534                              <1> 	;	; jsr r0,setimod / set modified flag
  4535                              <1> 	;retn
  4536                              <1> 	;	; rts r0 / return
  4537                              <1> 	; 24/12/2021
  4538 000045B1 E983050000          <1> 	jmp	setimod
  4539                              <1> 
  4540                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4541                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4542                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4543                              <1> 	;
  4544                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4545                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4546                              <1> 	; The file descriptor refers to a file open for reading or
  4547                              <1> 	; writing. The read (or write) pointer is set as follows:
  4548                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4549                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4550                              <1> 	;	  current location plus offset.
  4551                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4552                              <1> 	;	  size of file plus offset.
  4553                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4554                              <1> 	;
  4555                              <1> 	; Calling sequence:
  4556                              <1> 	;	sysseek; offset; ptrname
  4557                              <1> 	; Arguments:
  4558                              <1> 	;	offset - number of bytes desired to move 
  4559                              <1> 	;		 the r/w pointer
  4560                              <1> 	;	ptrname - a switch indicated above
  4561                              <1> 	;
  4562                              <1> 	; Inputs: r0 - file descriptor 
  4563                              <1> 	; Outputs: -
  4564                              <1> 	; ...............................................................
  4565                              <1> 	;	
  4566                              <1> 	; Retro UNIX 8086 v1 modification: 
  4567                              <1> 	;       'sysseek' system call has three arguments; so,
  4568                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4569                              <1> 	;	* 2nd argument, offset is in CX register
  4570                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4571                              <1> 	;	
  4572                              <1> 
  4573 000045B6 E822000000          <1> 	call	seektell
  4574                              <1> 	; AX = u.count
  4575                              <1> 	; BX = *u.fofp
  4576                              <1> 		; jsr r0,seektell / get proper value in u.count
  4577                              <1> 		; add u.base,u.count / add u.base to it
  4578 000045BB 0305[B8680000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4579 000045C1 8903                <1> 	mov	[ebx], eax
  4580                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4581 000045C3 E96AEDFFFF          <1> 	jmp	sysret
  4582                              <1> 		; br sysret4
  4583                              <1> 
  4584                              <1> systell: ; / get the r/w pointer
  4585                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4586                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4587                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4588                              <1> 	;
  4589                              <1> 	; Retro UNIX 8086 v1 modification:
  4590                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4591                              <1> 	; 	    it returns with error !
  4592                              <1> 	; Inputs: r0 - file descriptor 
  4593                              <1> 	; Outputs: r0 - file r/w pointer
  4594                              <1> 
  4595                              <1> 	;xor	ecx, ecx ; 0
  4596                              <1> 	;mov	edx, 1 ; 05/08/2013
  4597                              <1> 	; 24/12/2021
  4598 000045C8 29D2                <1> 	sub	edx, edx
  4599 000045CA FEC2                <1> 	inc	dl
  4600                              <1> 	; edx = 1
  4601                              <1> 	;call 	seektell
  4602 000045CC E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4603                              <1> 	;mov	ebx, [u.fofp]
  4604 000045D1 8B03                <1> 	mov	eax, [ebx]
  4605 000045D3 A3[98680000]        <1> 	mov	[u.r0], eax
  4606 000045D8 E955EDFFFF          <1> 	jmp	sysret
  4607                              <1> 
  4608                              <1> ; Original unix v1 'systell' system call:
  4609                              <1> 		; jsr r0,seektell
  4610                              <1> 		; br error4
  4611                              <1> 
  4612                              <1> seektell:
  4613                              <1> 	; 03/02/2022
  4614                              <1> 	; 03/01/2016
  4615                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4616                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4617                              <1> 	;
  4618                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4619                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4620                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4621                              <1> 	; getf. The i-node is brought into core and then u.count
  4622                              <1> 	; is checked to see it is a 0, 1, or 2.
  4623                              <1> 	; If it is 0 - u.count stays the same
  4624                              <1> 	;          1 - u.count = offset (u.fofp)
  4625                              <1> 	;	   2 - u.count = i.size (size of file)
  4626                              <1> 	; 	 		
  4627                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4628                              <1> 	;	Argument 1, file descriptor is in BX;
  4629                              <1> 	;	Argument 2, offset is in CX;
  4630                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4631                              <1> 	;
  4632                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4633                              <1> 	; call 	arg
  4634                              <1> 	;
  4635                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4636                              <1> 	;
  4637 000045DD 890D[B8680000]      <1> 	mov 	[u.base], ecx ; offset
  4638                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4639                              <1> seektell0:
  4640 000045E3 8915[BC680000]      <1> 	mov 	[u.count], edx
  4641                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4642                              <1> 	; mov	ax, bx
  4643                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4644                              <1> 			     ; / (index in u.fp list)
  4645                              <1> 	; call	getf
  4646                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4647                              <1> 	; BX = file descriptor (file number)
  4648 000045E9 E800FCFFFF          <1> 	call	getf1
  4649                              <1> 	; 03/02/2022
  4650 000045EE 09C0                <1> 	or	eax, eax
  4651                              <1> 	;or	ax, ax ; i-number of the file
  4652                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4653                              <1> 		             ; / put it on the stack
  4654                              <1> 	;jz	error
  4655                              <1> 		; beq error4 / if i-number is 0, not active so error
  4656 000045F0 750F                <1> 	jnz	short seektell1
  4657 000045F2 C705[ED680000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4657 000045FA 0000                <1>
  4658 000045FC E911EDFFFF          <1> 	jmp	error
  4659                              <1> seektell1:
  4660                              <1> 	;push	eax
  4661 00004601 80FC80              <1> 	cmp	ah, 80h
  4662 00004604 7203                <1> 	jb	short seektell2
  4663                              <1> 		; bgt .+4 / if its positive jump
  4664 00004606 66F7D8              <1> 	neg	ax
  4665                              <1> 		; neg r1 / if not make it positive
  4666                              <1> seektell2:
  4667 00004609 E821040000          <1> 	call	iget
  4668                              <1> 		; jsr r0,iget / get its i-node into core
  4669 0000460E 8B1D[A8680000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4670 00004614 803D[BC680000]01    <1> 	cmp	byte [u.count], 1
  4671                              <1> 		; cmp u.count,$1 / is ptr name =1
  4672 0000461B 7705                <1> 	ja	short seektell3
  4673                              <1> 		; blt 2f / no its zero
  4674 0000461D 740A                <1> 	je	short seektell_4
  4675                              <1> 		; beq 1f / yes its 1
  4676 0000461F 31C0                <1> 	xor	eax, eax
  4677                              <1> 	;jmp	short seektell_5
  4678 00004621 C3                  <1> 	retn
  4679                              <1> seektell3:
  4680                              <1> 	; 03/01/2016
  4681                              <1> 	;movzx	eax, word [i.size]
  4682 00004622 66A1[98650000]      <1>         mov   	ax, [i.size]
  4683                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4684                              <1>                                    ; / in file in u.count
  4685                              <1> 	;jmp	short seektell_5
  4686                              <1> 		; br 2f
  4687 00004628 C3                  <1> 	retn
  4688                              <1> seektell_4: ; 1: / ptrname =1
  4689                              <1> 	;mov	ebx, [u.fofp]
  4690 00004629 8B03                <1> 	mov	eax, [ebx]
  4691                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4692                              <1> ;seektell_5: ; 2: / ptrname =0
  4693                              <1> 	;mov	[u.count], eax
  4694                              <1> 	;pop	eax 
  4695                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4696 0000462B C3                  <1> 	retn
  4697                              <1> 		; rts r0
  4698                              <1> 
  4699                              <1> sysintr: ; / set interrupt handling
  4700                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4701                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4702                              <1> 	;
  4703                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4704                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4705                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4706                              <1> 	; If one does the interrupt character in the tty buffer is
  4707                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4708                              <1> 	; 'sysret' is just called.	
  4709                              <1> 	;
  4710                              <1> 	; Calling sequence:
  4711                              <1> 	;	sysintr; arg
  4712                              <1> 	; Argument:
  4713                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4714                              <1> 	;	    - if 1, intterupts cause their normal result
  4715                              <1> 	;		 i.e force an exit.
  4716                              <1> 	;	    - if arg is a location within the program,
  4717                              <1> 	;		control is passed to that location when
  4718                              <1> 	;		an interrupt occurs.	
  4719                              <1> 	; Inputs: -
  4720                              <1> 	; Outputs: -
  4721                              <1> 	; ...............................................................
  4722                              <1> 	;	
  4723                              <1> 	; Retro UNIX 8086 v1 modification: 
  4724                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4725                              <1> 	;	then branches into sysquit.
  4726                              <1> 	;
  4727 0000462C 66891D[DC680000]    <1> 	mov	[u.intr], bx
  4728                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4729                              <1> 		; br 1f / go into quit routine
  4730 00004633 E9FAECFFFF          <1> 	jmp	sysret
  4731                              <1> 
  4732                              <1> sysquit:
  4733                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4734                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4735                              <1> 	;
  4736                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4737                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4738                              <1> 	; tty exists. If one does the interrupt character in the tty
  4739                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4740                              <1> 	; 'sysret' is just called.	
  4741                              <1> 	;
  4742                              <1> 	; Calling sequence:
  4743                              <1> 	;	sysquit; arg
  4744                              <1> 	; Argument:
  4745                              <1> 	;	arg - if 0, this call diables quit signals from the
  4746                              <1> 	;		typewriter (ASCII FS)
  4747                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4748                              <1> 	;		cease and a core image to be produced.
  4749                              <1> 	;		 i.e force an exit.
  4750                              <1> 	;	    - if arg is an addres in the program,
  4751                              <1> 	;		a quit causes control to sent to that
  4752                              <1> 	;		location.	
  4753                              <1> 	; Inputs: -
  4754                              <1> 	; Outputs: -
  4755                              <1> 	; ...............................................................
  4756                              <1> 	;	
  4757                              <1> 	; Retro UNIX 8086 v1 modification: 
  4758                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4759                              <1> 	;	then branches into 'sysret'.
  4760                              <1> 	;
  4761 00004638 66891D[DE680000]    <1> 	mov	[u.quit], bx
  4762 0000463F E9EEECFFFF          <1> 	jmp	sysret
  4763                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4764                              <1> 	;1:
  4765                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4766                              <1> 			      ; / to r1
  4767                              <1> 		; beq sysret4 / return to user
  4768                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4769                              <1> 			   ; / in the tty buffer
  4770                              <1> 		; br sysret4 / return to user
  4771                              <1> 
  4772                              <1> syssetuid: ; / set process id
  4773                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4774                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4775                              <1> 	;
  4776                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4777                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4778                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4779                              <1> 	; Only the super user can make this call.	
  4780                              <1> 	;
  4781                              <1> 	; Calling sequence:
  4782                              <1> 	;	syssetuid
  4783                              <1> 	; Arguments: -
  4784                              <1> 	;
  4785                              <1> 	; Inputs: (u.r0) - contains the process id.
  4786                              <1> 	; Outputs: -
  4787                              <1> 	; ...............................................................
  4788                              <1> 	;	
  4789                              <1> 	; Retro UNIX 8086 v1 modification: 
  4790                              <1> 	;       BL contains the (new) user ID of the current process
  4791                              <1> 
  4792                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4793 00004644 3A1D[E5680000]      <1> 	cmp	bl, [u.ruid] 
  4794                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4795                              <1> 			       ; / id number
  4796 0000464A 741E                <1> 	je	short setuid1
  4797                              <1> 		; beq 1f / yes
  4798 0000464C 803D[E4680000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4799                              <1> 		; tstb u.uid / no, is current user the super user?
  4800                              <1> 	;ja	error
  4801                              <1> 		; bne error4 / no, error
  4802 00004653 760F                <1> 	jna	short setuid0
  4803 00004655 C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4803 0000465D 0000                <1>
  4804                              <1> 				; 'permission denied !' error
  4805 0000465F E9AEECFFFF          <1> 	jmp	error
  4806                              <1> setuid0:
  4807 00004664 881D[E5680000]      <1> 	mov	[u.ruid], bl
  4808                              <1> setuid1: ; 1:
  4809 0000466A 881D[E4680000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4810                              <1> 		; movb r1,u.uid / put process id in u.uid
  4811                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4812 00004670 E9BDECFFFF          <1> 	jmp	sysret
  4813                              <1> 		; br sysret4 / system return
  4814                              <1> 
  4815                              <1> sysgetuid: ; < get user id >
  4816                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4817                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4818                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4819                              <1> 	;
  4820                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4821                              <1> 	; The real user ID identifies the person who is logged in,
  4822                              <1> 	; in contradistinction to the effective user ID, which
  4823                              <1> 	; determines his access permission at each moment. It is thus
  4824                              <1> 	; useful to programs which operate using the 'set user ID'
  4825                              <1> 	; mode, to find out who invoked them.	
  4826                              <1> 	;
  4827                              <1> 	; Calling sequence:
  4828                              <1> 	;	syssetuid
  4829                              <1> 	; Arguments: -
  4830                              <1> 	;
  4831                              <1> 	; Inputs: -
  4832                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4833                              <1> 	; ...............................................................
  4834                              <1> 	;	
  4835                              <1> 	; Retro UNIX 8086 v1 modification: 
  4836                              <1> 	;       AL contains the real user ID at return.
  4837                              <1> 	;
  4838                              <1> 	;movzx 	eax, byte [u.ruid]
  4839                              <1> 	; 09/01/2022
  4840 00004675 A0[E5680000]        <1> 	mov	al, [u.ruid]
  4841 0000467A A3[98680000]        <1> 	mov	[u.r0], eax
  4842                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4843 0000467F E9AEECFFFF          <1> 	jmp	sysret
  4844                              <1> 		; br sysret4 / systerm return, sysret
  4845                              <1> 
  4846                              <1> anyi: 
  4847                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4848                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4849                              <1> 	;
  4850                              <1> 	; 'anyi' is called if a file deleted while open.
  4851                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4852                              <1> 	;
  4853                              <1> 	; INPUTS ->
  4854                              <1> 	;    r1 - contains an i-number
  4855                              <1> 	;    fsp - start of table containing open files
  4856                              <1> 	;
  4857                              <1> 	; OUTPUTS ->
  4858                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4859                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4860                              <1> 	;    if file not found - bit in i-node map is cleared
  4861                              <1> 	;    			 (i-node is freed)
  4862                              <1> 	;               all blocks related to i-node are freed
  4863                              <1> 	;	        all flags in i-node are cleared
  4864                              <1> 	; ((AX = R1)) input
  4865                              <1> 	;
  4866                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4867                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4868                              <1> 	;
  4869                              <1> 		; / r1 contains an i-number
  4870 00004684 BB[64660000]        <1> 	mov	ebx, fsp
  4871                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4872                              <1> anyi_1: ; 1:
  4873 00004689 663B03              <1> 	cmp	ax, [ebx]
  4874                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4875 0000468C 7433                <1> 	je	short anyi_3
  4876                              <1> 		; beq 1f / yes, 1f
  4877 0000468E 66F7D8              <1> 	neg	ax
  4878                              <1> 		; neg r1 / no complement r1
  4879 00004691 663B03              <1> 	cmp	ax, [ebx]
  4880                              <1> 		; cmp r1,(r2) / do they match now?
  4881 00004694 742B                <1> 	je	short anyi_3
  4882                              <1> 		; beq 1f / yes, transfer
  4883                              <1> 		; / i-numbers do not match
  4884 00004696 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4885                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4886                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4887 00004699 81FB[58680000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4888                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4889                              <1> 				; / are we at last entry in the table
  4890 0000469F 72E8                <1> 	jb	short anyi_1
  4891                              <1> 		; blt 1b / no, check next entries i-number
  4892                              <1> 	;cmp	ax, 32768
  4893 000046A1 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4894                              <1> 		; tst r1 / yes, no match
  4895                              <1> 		; bge .+4
  4896 000046A4 7203                <1> 	jb	short anyi_2
  4897 000046A6 66F7D8              <1> 	neg	ax
  4898                              <1> 		; neg r1 / make i-number positive
  4899                              <1> anyi_2:	
  4900 000046A9 E81A050000          <1> 	call	imap
  4901                              <1> 		; jsr r0,imap / get address of allocation bit 
  4902                              <1> 			    ; / in the i-map in r2
  4903                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4904                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4905                              <1>  	; not	dx
  4906 000046AE F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4907                              <1>         ;and	[ebx], dx
  4908 000046B0 2013                <1> 	and 	[ebx], dl 
  4909                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4910 000046B2 E8A4040000          <1> 	call	itrunc
  4911                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4912 000046B7 66C705[94650000]00- <1>  	mov 	word [i.flgs], 0
  4912 000046BF 00                  <1>
  4913                              <1> 		; clr i.flgs / clear all flags in the i-node
  4914 000046C0 C3                  <1> 	retn
  4915                              <1> 		;rts	r0 / return
  4916                              <1> anyi_3: ; 1: / i-numbers match
  4917 000046C1 FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4918                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4919                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4920 000046C4 C3                  <1> 	retn
  4921                              <1> 		; rts r0
  2107                                  %include 'u3.s'        ; 10/05/2015
  2108                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS3.INC
  2109                              <1> ; Last Modification: 24/12/2021
  2110                              <1> ; ----------------------------------------------------------------------------
  2111                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2112                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2113                              <1> ;
  2114                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2115                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2116                              <1> ; <Bell Laboratories (17/3/1972)>
  2117                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2118                              <1> ;
  2119                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2120                              <1> ;
  2121                              <1> ; ****************************************************************************
  2122                              <1> 
  2123                              <1> tswitch: ; Retro UNIX 386 v1
  2124                              <1> tswap:
  2125                              <1> 	; 01/09/2015
  2126                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2127                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2128                              <1> 	; time out swap, called when a user times out.
  2129                              <1> 	; the user is put on the low priority queue.
  2130                              <1> 	; This is done by making a link from the last user
  2131                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2132                              <1> 	; then he is swapped out.
  2133                              <1> 	;
  2134                              <1> 	; Retro UNIX 386 v1 modification ->
  2135                              <1> 	;       swap (software task switch) is performed by changing
  2136                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2137                              <1> 	;	as in Retro UNIX 8086 v1.
  2138                              <1> 	;
  2139                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2140                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2141                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2142                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2143                              <1> 	;	compatibles was using 1MB segmented memory 
  2144                              <1> 	;	in 8086/8088 times.
  2145                              <1> 	;
  2146                              <1> 	; INPUTS ->
  2147                              <1> 	;    u.uno - users process number
  2148                              <1> 	;    runq+4 - lowest priority queue
  2149                              <1> 	; OUTPUTS ->
  2150                              <1> 	;    r0 - users process number
  2151                              <1> 	;    r2 - lowest priority queue address
  2152                              <1> 	;
  2153                              <1> 	; ((AX = R0, BX = R2)) output
  2154                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2155                              <1> 	;
  2156 000046C5 A0[E7680000]        <1> 	mov 	al, [u.uno]
  2157                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2158                              <1> 		; mov  $runq+4,r2 
  2159                              <1> 			; / move lowest priority queue address to r2
  2160 000046CA E8CD000000          <1>         call 	putlu
  2161                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2162                              <1> 		             ; / u.uno's user
  2163                              <1> 
  2164                              <1> switch: ; Retro UNIX 386 v1
  2165                              <1> swap:
  2166                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2167                              <1> 	; 02/09/2015
  2168                              <1> 	; 01/09/2015
  2169                              <1> 	; 31/08/2015
  2170                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2171                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2172                              <1> 	; 'swap' is routine that controls the swapping of processes
  2173                              <1> 	; in and out of core.
  2174                              <1> 	;
  2175                              <1> 	; Retro UNIX 386 v1 modification ->
  2176                              <1> 	;       swap (software task switch) is performed by changing
  2177                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2178                              <1> 	;	as in Retro UNIX 8086 v1.
  2179                              <1> 	;
  2180                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2181                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2182                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2183                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2184                              <1> 	;	compatibles was using 1MB segmented memory 
  2185                              <1> 	;	in 8086/8088 times.
  2186                              <1> 	;
  2187                              <1> 	; INPUTS ->
  2188                              <1> 	;    runq table - contains processes to run.
  2189                              <1> 	;    p.link - contains next process in line to be run.
  2190                              <1> 	;    u.uno - process number of process in core	
  2191                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2192                              <1> 	; OUTPUTS ->
  2193                              <1> 	;    (original unix v1 -> present process to its disk block)
  2194                              <1> 	;    (original unix v1 -> new process into core -> 
  2195                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2196                              <1> 	;	   for new process)
  2197                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2198                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2199                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2200                              <1> 	;	 for now, it will swap the process if there is not
  2201                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2202                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2203                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2204                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2205                              <1> 	;
  2206                              <1> 	;    u.pri -points to highest priority run Q.
  2207                              <1> 	;    r2 - points to the run queue.
  2208                              <1> 	;    r1 - contains new process number
  2209                              <1> 	;    r0 - points to place in routine or process that called
  2210                              <1> 	;	  swap all user parameters
  2211                              <1> 	;				
  2212                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2213                              <1> 	;
  2214                              <1> swap_0:
  2215                              <1> 		;mov $300,*$ps / processor priority = 6
  2216 000046CF BE[88680000]        <1> 	mov	esi, runq
  2217                              <1> 		; mov $runq,r2 / r2 points to runq table
  2218                              <1> swap_1: ; 1: / search runq table for highest priority process
  2219 000046D4 668B06              <1> 	mov	ax, [esi]
  2220 000046D7 6621C0              <1> 	and 	ax, ax
  2221                              <1>        		; tst (r2)+ / are there any processes to run 
  2222                              <1> 			  ; / in this Q entry
  2223 000046DA 7507                <1> 	jnz	short swap_2
  2224                              <1>        		; bne 1f / yes, process 1f
  2225                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2226                              <1> 			       ; / to end of table
  2227                              <1> 		; bne 1b / if not at end, go back
  2228 000046DC E8E0000000          <1> 	call	idle
  2229                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2230                              <1> 				       ; / all queues are empty
  2231 000046E1 EBF1                <1> 	jmp	short swap_1
  2232                              <1> 		; br swap
  2233                              <1> swap_2: ; 1:
  2234 000046E3 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2235                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2236                              <1>  		; mov r2,u.pri / set present user to this run queue
  2237                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2238 000046E6 38E0                <1> 	cmp	al, ah
  2239                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2240                              <1> 			      ; / in this Q to be run
  2241 000046E8 740A                <1> 	je	short swap_3
  2242                              <1>        		; beq 1f / yes
  2243                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2244                              <1> 	;movzx	ebx, al
  2245 000046EA 8AA3[03660000]      <1> 	mov	ah, [ebx+p.link-1] 
  2246 000046F0 8826                <1>        	mov	[esi], ah
  2247                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2248                              <1> 				       ; / in line into run queue
  2249 000046F2 EB05                <1> 	jmp	short swap_4
  2250                              <1>        		; br 2f
  2251                              <1> swap_3: ; 1:
  2252                              <1> 	;xor	dx, dx
  2253                              <1> 	; 24/12/2021
  2254 000046F4 31D2                <1> 	xor	edx, edx
  2255 000046F6 668916              <1> 	mov	[esi], dx
  2256                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2257                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2258                              <1>       ; / in new process if required
  2259                              <1>        		; clr *$ps / clear processor status
  2260 000046F9 8A25[E7680000]      <1> 	mov 	ah, [u.uno]
  2261 000046FF 38C4                <1> 	cmp	ah, al
  2262                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2263                              <1> 			      ; / the process in core?
  2264 00004701 743B                <1>        	je	short swap_8
  2265                              <1>        		; beq 2f / yes, don't have to swap
  2266                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2267                              <1> 			   ; / (address in routine that called swap)
  2268                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2269                              <1> 	; 01/09/2015
  2270                              <1> 	;mov	[u.usp], esp
  2271                              <1>        		; mov sp,u.usp / save stack pointer
  2272                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2273                              <1> 			       ; / to the stack pointer
  2274 00004703 08E4                <1> 	or	ah, ah
  2275                              <1>        		; tstb u.uno / is the process # = 0
  2276 00004705 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2277                              <1> 		; beq 1f / yes, kill process by overwriting
  2278                              <1> 	; 02/09/2015
  2279 00004707 8925[94680000]      <1> 	mov	[u.usp], esp ; return address for 'syswait' & 'sleep'
  2280                              <1> 	;
  2281 0000470D E834000000          <1> 	call	wswap
  2282                              <1> 		; jsr r0,wswap / write out core to disk
  2283                              <1> 	 ; 31/08/2015
  2284                              <1> 	;movzx	ebx, al ; New (running) process number
  2285 00004712 EB1C                <1> 	jmp 	short swap_7
  2286                              <1> swap_6:
  2287                              <1> 	; 31/08/2015
  2288                              <1> 	; Deallocate memory pages belong to the process
  2289                              <1> 	; which is being terminated
  2290                              <1> 	; 14/05/2015 ('sysexit')
  2291                              <1>  	; Deallocate memory pages of the process
  2292                              <1> 	; (Retro UNIX 386 v1 modification !)
  2293                              <1> 	;
  2294                              <1> 	; movzx ebx, al
  2295 00004714 53                  <1> 	push	ebx
  2296 00004715 A1[F1680000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2297 0000471A 8B1D[F5680000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2298 00004720 E80CE0FFFF          <1> 	call	deallocate_page_dir
  2299 00004725 A1[E8680000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2300 0000472A E89AE0FFFF          <1> 	call	deallocate_page
  2301 0000472F 5B                  <1> 	pop	ebx
  2302                              <1> swap_7: ;1: 
  2303                              <1> 	; 02/09/2015
  2304                              <1> 	; 31/08/2015
  2305                              <1> 	; 14/05/2015
  2306 00004730 C0E302              <1> 	shl	bl, 2 ; * 4 
  2307 00004733 8B83[20660000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2308                              <1> 	;cli
  2309 00004739 E831000000          <1> 	call	rswap
  2310                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2311                              <1> 		; jsr r0,rswap / read new process into core
  2312                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2313                              <1> 			      ; / to his program to its normal
  2314                              <1> 	; 01/09/2015
  2315                              <1> 	;mov	esp, [u.usp]	
  2316                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2317                              <1> 			     ; / new process stack
  2318                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2319                              <1> 			     ; / that just got swapped in, left off.,
  2320                              <1> 			     ; / i.e., transfer control to new process
  2321                              <1> 	;sti
  2322                              <1> swap_8: ;2:
  2323                              <1> 	; RETRO UNIX 8086 v1 modification !
  2324 0000473E C605[DA680000]04    <1> 	mov	byte [u.quant], time_count 
  2325                              <1> 		; movb $30.,uquant / initialize process time quantum
  2326 00004745 C3                  <1> 	retn
  2327                              <1> 		; rts r0 / return
  2328                              <1> 
  2329                              <1> wswap:  ; < swap out, swap to disk >
  2330                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2331                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2332                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2333                              <1> 	; appropriate disk area.
  2334                              <1> 	;
  2335                              <1> 	; Retro UNIX 386 v1 modification ->
  2336                              <1> 	;       User (u) structure content and the user's register content
  2337                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2338                              <1> 	;	saving 'u' structure and user registers for task switching).
  2339                              <1> 	;	u.usp - points to kernel stack address which contains
  2340                              <1> 	;		user's registers while entering system call.  
  2341                              <1> 	;	u.sp  - points to kernel stack address 
  2342                              <1> 	;		to return from system call -for IRET-.
  2343                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2344                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2345                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2346                              <1> 	;
  2347                              <1> 	; Retro UNIX 8086 v1 modification ->
  2348                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2349                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2350                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2351                              <1> 	;	compatibles was using 1MB segmented memory 
  2352                              <1> 	;	in 8086/8088 times.
  2353                              <1> 	;
  2354                              <1> 	; INPUTS ->
  2355                              <1> 	;    u.break - points to end of program
  2356                              <1> 	;    u.usp - stack pointer at the moment of swap
  2357                              <1> 	;    core - beginning of process program		
  2358                              <1> 	;    ecore - end of core 	
  2359                              <1> 	;    user - start of user parameter area		
  2360                              <1> 	;    u.uno - user process number	
  2361                              <1> 	;    p.dska - holds block number of process	
  2362                              <1> 	; OUTPUTS ->
  2363                              <1> 	;    swp I/O queue
  2364                              <1> 	;    p.break - negative word count of process 
  2365                              <1> 	;    r1 - process disk address	
  2366                              <1> 	;    r2 - negative word count
  2367                              <1> 	;
  2368                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2369                              <1> 	;
  2370                              <1> 	; INPUTS ->
  2371                              <1> 	;    u.uno - process number (to be swapped out)
  2372                              <1> 	; OUTPUTS ->
  2373                              <1> 	;    none
  2374                              <1> 	;
  2375                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2376                              <1> 	;
  2377 00004746 8B3D[E8680000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2378 0000474C B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2379 00004751 BE[90680000]        <1> 	mov	esi, user ; active user (u) structure	
  2380 00004756 F3A5                <1> 	rep	movsd
  2381                              <1> 	;
  2382 00004758 8B35[94680000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2383                              <1> 			     ;      points to user registers)
  2384 0000475E 8B0D[90680000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2385                              <1> 			     ; (for IRET)
  2386                              <1> 			     ; [u.sp] -> EIP (user)
  2387                              <1> 			     ; [u.sp+4]-> CS (user)
  2388                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2389                              <1> 			     ; [u.sp+12] -> ESP (user)
  2390                              <1> 			     ; [u.sp+16] -> SS (user)	
  2391 00004764 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2392 00004766 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2393                              <1> 			     ; (for IRET) 	
  2394 00004769 C1E902              <1> 	shr	ecx, 2	     		
  2395 0000476C F3A5                <1> 	rep	movsd
  2396 0000476E C3                  <1> 	retn
  2397                              <1> 
  2398                              <1> 	; Original UNIX v1 'wswap' routine:
  2399                              <1> 	; wswap:
  2400                              <1> 		; mov *$30,u.emt / determines handling of emts
  2401                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2402                              <1> 				; / illegal instructions
  2403                              <1> 		; mov u.break,r2 / put process program break address in r2
  2404                              <1> 		; inc r2 / add 1 to it 
  2405                              <1> 		; bic $1,r2 / make it even
  2406                              <1> 		; mov r2,u.break / set break to an even location
  2407                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2408                              <1> 			     ; / at moment of swap in r3
  2409                              <1> 		; cmp r2,$core / is u.break less than $core
  2410                              <1> 		; blos 2f / yes
  2411                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2412                              <1>        		; bhis 2f / yes
  2413                              <1> 	; 1:
  2414                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2415                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2416                              <1> 		; bne 1b / no, keep packing
  2417                              <1> 	 	; br 1f / yes
  2418                              <1> 	; 2:
  2419                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2420                              <1> 	; 1:
  2421                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2422                              <1> 			   ; / (user up to end of stack gets written out)
  2423                              <1> 		; neg r2 / make it negative
  2424                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2425                              <1> 		; mov r2,swp+4 / word count
  2426                              <1> 		; movb u.uno,r1 / move user process number to r1
  2427                              <1> 		; asl r1 / x2 for index
  2428                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2429                              <1> 				     ; / into the p.break table
  2430                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2431                              <1> 				    ; /	for process to r1
  2432                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2433                              <1> 			     ; / (block number)
  2434                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2435                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2436                              <1> 	; 1:
  2437                              <1>        		; tstb swp+1 / is lt done writing?
  2438                              <1>        		; bne 1b / no, wait
  2439                              <1> 		; rts r0 / yes, return to swap
  2440                              <1> 
  2441                              <1> rswap:  ; < swap in, swap from disk >
  2442                              <1> 	; 15/09/2015
  2443                              <1> 	; 28/08/2015
  2444                              <1> 	; 14/05/2015
  2445                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2446                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2447                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2448                              <1> 	; from disk into core.
  2449                              <1> 	;
  2450                              <1> 	; Retro UNIX 386 v1 modification ->
  2451                              <1> 	;       User (u) structure content and the user's register content
  2452                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2453                              <1> 	;	saving 'u' structure and user registers for task switching).
  2454                              <1> 	;	u.usp - points to kernel stack address which contains
  2455                              <1> 	;		user's registers while entering system call.  
  2456                              <1> 	;	u.sp  - points to kernel stack address 
  2457                              <1> 	;		to return from system call -for IRET-.
  2458                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2459                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2460                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2461                              <1> 	;
  2462                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2463                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2464                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2465                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2466                              <1> 	;	compatibles was using 1MB segmented memory 
  2467                              <1> 	;	in 8086/8088 times.
  2468                              <1> 	;
  2469                              <1> 	; INPUTS ->
  2470                              <1> 	;    r1 - process number of process to be read in
  2471                              <1> 	;    p.break - negative of word count of process 
  2472                              <1> 	;    p.dska - disk address of the process		
  2473                              <1> 	;    u.emt - determines handling of emt's 	
  2474                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2475                              <1> 	; OUTPUTS ->
  2476                              <1> 	;    8 = (u.ilgins)
  2477                              <1> 	;    24 = (u.emt)
  2478                              <1> 	;    swp - bit 10 is set to indicate read 
  2479                              <1> 	;		(bit 15=0 when reading is done)	
  2480                              <1> 	;    swp+2 - disk block address
  2481                              <1> 	;    swp+4 - negative word count 	
  2482                              <1> 	;      ((swp+6 - address of user structure)) 
  2483                              <1> 	;
  2484                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2485                              <1> 	;
  2486                              <1> 	; INPUTS ->
  2487                              <1> 	;    AL	- new process number (to be swapped in)	 
  2488                              <1> 	; OUTPUTS ->
  2489                              <1> 	;    none
  2490                              <1> 	;
  2491                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2492                              <1> 	;
  2493                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2494 0000476F 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2495 00004771 B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2496 00004776 BF[90680000]        <1> 	mov	edi, user ; active user (u) structure	
  2497 0000477B F3A5                <1> 	rep	movsd
  2498 0000477D 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2499 0000477E 8B3D[94680000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2500                              <1> 			     ;      points to user registers)
  2501 00004784 8B0D[90680000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2502                              <1> 			     ; (for IRET)
  2503                              <1> 			     ; [u.sp] -> EIP (user)
  2504                              <1> 			     ; [u.sp+4]-> CS (user)
  2505                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2506                              <1> 			     ; [u.sp+12] -> ESP (user)
  2507                              <1> 			     ; [u.sp+16] -> SS (user)		
  2508                              <1> 	; 28/08/2015
  2509 0000478A 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2510 0000478C 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2511                              <1> 			     ; (for IRET) 	
  2512 0000478F C1E902              <1> 	shr	ecx, 2	       		
  2513 00004792 F3A5                <1> 	rep	movsd
  2514 00004794 8B25[94680000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2515 0000479A 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2516 0000479B C3                  <1> 	retn
  2517                              <1> 
  2518                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2519                              <1> 	;rswap:
  2520                              <1>        		; asl r1 / process number x2 for index
  2521                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2522                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2523                              <1>        		; bis $2000,swp / read
  2524                              <1>        		; jsr r0,ppoke / read it in 
  2525                              <1> 	; 1:
  2526                              <1>        		; tstb swp+1 / done
  2527                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2528                              <1>        		; mov u.emt,*$30 / yes move these
  2529                              <1>        		; mov u.ilgins,*$10 / back
  2530                              <1>        		; rts r0 / return
  2531                              <1> 
  2532                              <1> 	;unpack: ; / move stack back to its normal place
  2533                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2534                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2535                              <1> 		; blos 2f / yes, return
  2536                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2537                              <1> 			     ; / before swapping
  2538                              <1> 		; bhis 2f / yes, return
  2539                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2540                              <1> 		; add r3,r2
  2541                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2542                              <1> 	; 1:
  2543                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2544                              <1> 		; cmp r2,u.break / in core
  2545                              <1> 		; bne 1b
  2546                              <1> 	; 2:
  2547                              <1>        		; rts r0
  2548                              <1> 
  2549                              <1> putlu: 
  2550                              <1> 	; 12/09/2015
  2551                              <1> 	; 02/09/2015
  2552                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2553                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2554                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2555                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2556                              <1> 	; the last process on the queue to process in r1 by putting
  2557                              <1> 	; the process number in r1 into the last process's link.
  2558                              <1> 	;
  2559                              <1> 	; INPUTS ->
  2560                              <1> 	;    r1 - user process number
  2561                              <1> 	;    r2 - points to lowest priority queue 
  2562                              <1> 	;    p.dska - disk address of the process		
  2563                              <1> 	;    u.emt - determines handling of emt's 	
  2564                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2565                              <1> 	; OUTPUTS ->
  2566                              <1> 	;    r3 - process number of last process on the queue upon
  2567                              <1> 	;	  entering putlu
  2568                              <1> 	;    p.link-1 + r3 - process number in r1
  2569                              <1> 	;    r2 - points to lowest priority queue
  2570                              <1> 	;
  2571                              <1> 	; ((Modified registers: EDX, EBX)) 
  2572                              <1> 	;
  2573                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2574                              <1> 
  2575                              <1> 	; eBX = r2
  2576                              <1> 	; eAX = r1 (AL=r1b)
  2577                              <1> 
  2578 0000479C BB[88680000]        <1> 	mov	ebx, runq
  2579 000047A1 0FB613              <1> 	movzx  	edx, byte [ebx]
  2580 000047A4 43                  <1> 	inc	ebx
  2581 000047A5 20D2                <1> 	and	dl, dl
  2582                              <1> 		; tstb (r2)+ / is queue empty?
  2583 000047A7 740A                <1>        	jz	short putlu_1
  2584                              <1> 		; beq 1f / yes, branch
  2585 000047A9 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2586                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2587                              <1> 			     ; / in r3
  2588 000047AB 8882[03660000]      <1>        	mov	[edx+p.link-1], al
  2589                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2590                              <1> 			     ; / "last users" link
  2591 000047B1 EB03                <1> 	jmp	short putlu_2
  2592                              <1> 		; br 2f /
  2593                              <1> putlu_1: ; 1:
  2594 000047B3 8843FF              <1> 	mov	[ebx-1], al
  2595                              <1>        		; movb r1,-1(r2) / user is only user; 
  2596                              <1> 			    ; / put process no. at beginning and at end
  2597                              <1> putlu_2: ; 2: 
  2598 000047B6 8803                <1> 	mov	[ebx], al
  2599                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2600                              <1> 			     ; / on the queue
  2601 000047B8 88C2                <1> 	mov	dl, al
  2602 000047BA 88B2[03660000]      <1>         mov     [edx+p.link-1], dh ; 0
  2603                              <1> 		; dec r2 / restore r2
  2604 000047C0 C3                  <1>         retn
  2605                              <1> 		; rts r0
  2606                              <1> 
  2607                              <1> ;copyz:
  2608                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2609                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2610                              <1> ;       mov     (r0)+,r1
  2611                              <1> ;       mov     (r0)+,r2
  2612                              <1> ;1:
  2613                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2614                              <1> ;       cmp     r1,r2 
  2615                              <1> ;       blo     1b
  2616                              <1> ;       mov     (sp)+,r2 / restore r2
  2617                              <1> ;       mov     (sp)+,r1 / restore r1
  2618                              <1> ;       rts     r0 
  2619                              <1> 
  2620                              <1> idle:
  2621                              <1> 	; 01/09/2015
  2622                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2623                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2624                              <1> 	; (idle & wait loop)
  2625                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2626                              <1> 	; idle procedure!
  2627                              <1>       	;
  2628                              <1>   	; 01/09/2015
  2629 000047C1 FB                  <1> 	sti
  2630                              <1>       	; 29/07/2013
  2631 000047C2 F4                  <1>       	hlt
  2632 000047C3 90                  <1>       	nop ; 10/10/2013
  2633 000047C4 90                  <1>       	nop
  2634 000047C5 90                  <1>       	nop
  2635                              <1>       	; 23/10/2013
  2636 000047C6 90                  <1>       	nop
  2637 000047C7 90                  <1>       	nop
  2638 000047C8 90                  <1>       	nop
  2639 000047C9 90                  <1>       	nop
  2640 000047CA C3                  <1>       	retn      
  2641                              <1> 
  2642                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2643                              <1> 	;clr *$ps / clear ps
  2644                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2645                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2646                              <1> 	;1 / wait for interrupt
  2647                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2648                              <1> 	;mov (sp)+,*$ps
  2649                              <1> 	;rts r0
  2650                              <1> 
  2651                              <1> clear:
  2652                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2653                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2654                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2655                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2656                              <1> 	; on the current device (cdev)
  2657                              <1> 	;	
  2658                              <1> 	; INPUTS ->
  2659                              <1> 	;    r1 - block number of block to be zeroed
  2660                              <1> 	;    cdev - current device number 
  2661                              <1> 	; OUTPUTS ->
  2662                              <1> 	;    a zeroed I/O buffer onto the current device
  2663                              <1> 	;    r1 - points to last entry in the I/O buffer
  2664                              <1> 	;
  2665                              <1> 	; ((AX = R1)) input/output
  2666                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2667                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2668                              <1> 
  2669 000047CB E8A20E0000          <1> 	call 	wslot
  2670                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2671                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2672 000047D0 89DF                <1> 	mov	edi, ebx ; r5
  2673 000047D2 89C2                <1> 	mov	edx, eax
  2674 000047D4 B980000000          <1> 	mov	ecx, 128
  2675                              <1> 		; mov $256.,r3
  2676 000047D9 31C0                <1> 	xor	eax, eax
  2677 000047DB F3AB                <1> 	rep	stosd
  2678 000047DD 89D0                <1> 	mov	eax, edx
  2679                              <1> ; 1: 
  2680                              <1>        		; clr (r5)+ / zero data word in buffer
  2681                              <1>        		; dec r3
  2682                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2683                              <1> 	;call	dskwr
  2684                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2685                              <1>                              ; / block specified in r1
  2686                              <1> 	; eAX (r1) = block number
  2687                              <1> 	;retn
  2688                              <1> 		; rts r0
  2689                              <1> 	; 24/12/2021
  2690 000047DF E9AA0E0000          <1> 	jmp	dskwr
  2108                                  %include 'u4.s'        ; 15/04/2015
  2109                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS4.INC
  2110                              <1> ; Last Modification: 26/02/2022
  2111                              <1> ; ----------------------------------------------------------------------------
  2112                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2113                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2114                              <1> ;
  2115                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2116                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2117                              <1> ; <Bell Laboratories (17/3/1972)>
  2118                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2119                              <1> ;
  2120                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2121                              <1> ;
  2122                              <1> ; ****************************************************************************
  2123                              <1> 
  2124                              <1> ;setisp:
  2125                              <1>        ;mov     r1,-(sp)
  2126                              <1>        ;mov     r2,-(sp)
  2127                              <1>        ;mov     r3,-(sp)
  2128                              <1>        ;mov     clockp,-(sp)
  2129                              <1>        ;mov     $s.syst+2,clockp
  2130                              <1>        ;jmp     (r0)
  2131                              <1> 
  2132                              <1> clock: ; / interrupt from 60 cycle clock
  2133                              <1> 	
  2134                              <1> 	; 14/10/2015
  2135                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2136                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2137                              <1> 
  2138                              <1>        ;mov     r0,-(sp) / save r0
  2139                              <1>        ;tst     *$lks / restart clock?
  2140                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2141                              <1>        ;inc     (r0)
  2142                              <1>        ;bne     1f
  2143                              <1>        ;inc     -(r0)
  2144                              <1> ;1:
  2145                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2146                              <1>        ;inc     (r0)
  2147                              <1>        ;bne     1f
  2148                              <1>        ;inc     -(r0)
  2149                              <1> ;1:
  2150                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2151                              <1> 
  2152 000047E4 803D[DA680000]00    <1> 	cmp	byte [u.quant], 0
  2153 000047EB 772C                <1> 	ja	short clk_1
  2154                              <1> 	;
  2155 000047ED 803D[8D680000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2156 000047F4 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2157 000047F6 803D[E7680000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2158 000047FD 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2159 000047FF 66833D[DC680000]00  <1> 	cmp	word [u.intr], 0
  2160 00004807 7616                <1> 	jna	short clk_2
  2161                              <1> clk_0:
  2162                              <1> 	; 14/10/2015
  2163 00004809 FE05[8D680000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2164 0000480F 58                  <1> 	pop	eax ; return address to the timer interrupt
  2165                              <1> 	;
  2166 00004810 B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2167                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2168 00004812 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2169                              <1> 	;
  2170 00004814 E97EEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2171                              <1> clk_1:
  2172 00004819 FE0D[DA680000]      <1> 	dec	byte [u.quant]
  2173                              <1> clk_2:
  2174 0000481F C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2175                              <1> 
  2176                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2177                              <1> 
  2178                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2179                              <1>        ;decb    (r0)
  2180                              <1>        ;bge     1f / if less than 0
  2181                              <1>        ;clrb    (r0) / make it 0
  2182                              <1> ;1: / decrement time out counts return now if priority was not 0
  2183                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2184                              <1>        ;bge     2f / yes, check time outs
  2185                              <1>        ;tstb    (r0) / no, user timed out?
  2186                              <1>        ;bne     1f / no
  2187                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2188                              <1>        ;bne     1f / no, 1f
  2189                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2190                              <1>        ;sys     0 / sysrele
  2191                              <1>        ;rti
  2192                              <1> ;2: / priority is high so just decrement time out counts
  2193                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2194                              <1> ;2:
  2195                              <1>        ;tstb    (r0) / is the time out?
  2196                              <1>        ;beq     3f / yes, 3f (get next entry)
  2197                              <1>        ;decb    (r0) / no, decrement the time
  2198                              <1>        ;bne     3f / isit zero now?
  2199                              <1>        ;incb    (r0) / yes, increment the time
  2200                              <1> ;3:
  2201                              <1>        ;inc     r0 / next entry
  2202                              <1>        ;cmp     r0,$touts / end of toutt table?
  2203                              <1>        ;blo     2b / no, check this entry
  2204                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2205                              <1>        ;rti / return from interrupt
  2206                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2207                              <1>        ;mov     (sp)+,r0 / restore r0
  2208                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2209                              <1>        ;jsr     r0,setisp / save registers
  2210                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2211                              <1>                                ;  / the table
  2212                              <1> ;1:
  2213                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2214                              <1>        ;beq     2f / yes
  2215                              <1>        ;decb    toutt(r0) / no, decrement the time
  2216                              <1>        ;bne     2f / is the time 0, now
  2217                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2218                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2219                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2220                              <1> ;2:
  2221                              <1>        ;dec     r0 / set up r0 for next entry
  2222                              <1>        ;bge     1b / finished? , no, go back
  2223                              <1>        ;br      retisp / yes, restore registers and do a rti
  2224                              <1> 
  2225                              <1> ;retisp:
  2226                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2227                              <1>        ;mov     (sp)+,r3
  2228                              <1>        ;mov     (sp)+,r2
  2229                              <1>        ;mov     (sp)+,r1
  2230                              <1>        ;mov     (sp)+,r0
  2231                              <1>        ;rti     / return from interrupt
  2232                              <1> 
  2233                              <1> 
  2234                              <1> wakeup: ; / wakeup processes waiting for an event 
  2235                              <1> 	; / by linking them to the queue
  2236                              <1> 	;
  2237                              <1> 	; 26/02/2022
  2238                              <1> 	; 15/09/2015
  2239                              <1> 	; 29/06/2015
  2240                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2241                              <1> 	;
  2242                              <1> 	; 15/05/2013 - 02/06/2014
  2243                              <1> 	; Retro UNIX 8086 v1 modification !
  2244                              <1> 	; (Process/task switching routine by using
  2245                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2246                              <1> 	;
  2247                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2248                              <1> 	; sleeping in the specified wait channel by creating a link 
  2249                              <1> 	; to it from the last user process on the run queue.
  2250                              <1> 	; If there is no process to wake up, nothing happens.
  2251                              <1> 	;
  2252                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2253                              <1> 	; 'switching' status of the current process (owns current tty)
  2254                              <1> 	; (via alt + function keys) to a process which has highest
  2255                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2256                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2257                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2258                              <1> 	; tty for tty switching by keyboard.)	 
  2259                              <1> 	; 
  2260                              <1> 	; INPUT -> 
  2261                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2262                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2263                              <1> 	;
  2264                              <1> 	; ((modified registers: EAX, EBX))
  2265                              <1> 	;
  2266 00004820 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2267 00004823 81C3[38650000]      <1> 	add	ebx, wlist
  2268 00004829 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2269 0000482B 20C0                <1> 	and	al, al
  2270 0000482D 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2271                              <1> 	;
  2272 0000482F 30E4                <1> 	xor	ah, ah
  2273 00004831 8825[DA680000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2274 00004837 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2275                              <1> 	; 15/09/2015
  2276 00004839 0FB6D8              <1> 	movzx	ebx, al
  2277                              <1> 	; 26/02/2022 (p.waitc is not used)
  2278                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2279 0000483C FEC4                <1> 	inc	ah
  2280 0000483E 88A3[13660000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2281                              <1> 	;
  2282 00004844 57                  <1> 	push	edi
  2283 00004845 52                  <1> 	push	edx
  2284 00004846 E851FFFFFF          <1> 	call	putlu
  2285 0000484B 5A                  <1> 	pop	edx
  2286 0000484C 5F                  <1> 	pop	edi
  2287                              <1> wa0:
  2288 0000484D C3                  <1> 	retn
  2289                              <1> 
  2290                              <1> sleep: 
  2291                              <1> 	; 26/02/2022
  2292                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2293                              <1> 	; 15/09/2015
  2294                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2295                              <1> 	;
  2296                              <1> 	; 09/05/2013 - 20/03/2014
  2297                              <1> 	;
  2298                              <1> 	; Retro UNIX 8086 v1 modification !
  2299                              <1> 	; (Process/task switching and quit routine by using
  2300                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2301                              <1> 	;
  2302                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2303                              <1> 	; tty and tape output or input becomes available
  2304                              <1> 	; and process is put on waiting channel and swapped out,
  2305                              <1> 	; then -when the tty or tape is ready to write or read-
  2306                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2307                              <1> 	;
  2308                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2309                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2310                              <1> 	; status of the current process also INT 1Ch will count down
  2311                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2312                              <1> 	; to tty buffer of the current process and kernel will get
  2313                              <1> 	; user input by using tty buffer of the current process
  2314                              <1> 	; (instead of standard INT 16h interrupt).
  2315                              <1> 	; TTY output will be redirected to related video page of text mode
  2316                              <1> 	; (INT 10h will be called with different video page depending
  2317                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2318                              <1> 	; pseudo screens.)
  2319                              <1> 	;
  2320                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2321                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2322                              <1> 	; characters/data on serial port(s).
  2323                              <1> 	;
  2324                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2325                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2326                              <1> 	; 
  2327                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2328                              <1> 	;
  2329                              <1> 	;; 05/10/2013
  2330                              <1>         ;10/12/2013
  2331                              <1> 	;cmp   byte [u.uno], 1
  2332                              <1>         ;ja    short sleep0
  2333                              <1> 	;retn
  2334                              <1> 
  2335                              <1> 	; 20/03/2014
  2336                              <1> 	;mov	bx, [runq]
  2337                              <1> 	;cmp	bl, bh
  2338                              <1> 	;jne	short sleep0	
  2339                              <1> 	; 25/02/2014
  2340                              <1> 	;cmp word ptr [runq], 0
  2341                              <1> 	;ja short sleep0	
  2342                              <1> 	;retn
  2343                              <1> sleep0:
  2344                              <1> 	;
  2345 0000484E E849000000          <1> 	call	isintr
  2346                              <1> 	;jnz	sysret
  2347                              <1> 		; / wait for event
  2348                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2349                              <1> 			      ; / or quit from user
  2350                              <1>                		; br 2f / something happened
  2351                              <1> 			      ; / yes, his interrupt so return
  2352                              <1>                      	      ;	/ to user
  2353                              <1> 	; 24/12/2021
  2354 00004853 7405                <1> 	jz	short sleep_2
  2355                              <1> sleep_3:
  2356 00004855 E9D8EAFFFF          <1> 	jmp	sysret
  2357                              <1> sleep_2:
  2358                              <1> 	; 30/06/2015
  2359 0000485A 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2360 0000485D 81C3[38650000]      <1> 	add	ebx, wlist
  2361 00004863 8A03                <1> 	mov	al, [ebx]
  2362 00004865 20C0                <1> 	and	al, al
  2363 00004867 7407                <1> 	jz	short sleep1
  2364 00004869 53                  <1> 	push	ebx
  2365 0000486A E82DFFFFFF          <1> 	call	putlu
  2366 0000486F 5B                  <1> 	pop	ebx
  2367                              <1> sleep1:
  2368 00004870 A0[E7680000]        <1> 	mov	al, [u.uno]    
  2369 00004875 8803                <1>   	mov	[ebx], al 	; put the process number
  2370                              <1> 				; in the wait channel
  2371                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2372                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2373                              <1> 				     ; / on the stack
  2374                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2375                              <1> 				     ; / to put to sleep in there
  2376                              <1>         ; 15/09/2015
  2377 00004877 0FB6D8              <1> 	movzx	ebx, al
  2378 0000487A C683[13660000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2379                              <1> 	; 26/02/2022 (p.waitc is not used)
  2380                              <1> 	;inc	ah
  2381                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2382                              <1> 	;
  2383 00004881 66FF35[7B680000]    <1> 	push    word [cdev]
  2384                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2385 00004888 E842FEFFFF          <1> 	call	swap
  2386                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2387 0000488D 668F05[7B680000]    <1>         pop     word [cdev]
  2388                              <1> 		; mov (sp)+,cdev / restore device
  2389 00004894 E803000000          <1> 	call	isintr
  2390                              <1> 	; 22/09/2013
  2391                              <1> 	;jnz	sysret         
  2392                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2393                              <1>                		; br 2f / yes, return to new user
  2394                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2395                              <1> 				; / originally on the wait channel
  2396                              <1>        		; beq 1f / if 0 branch
  2397                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2398                              <1>        		; mov $300,*$ps / processor priority = 6
  2399                              <1> 		; jsr r0,putlu / create link to old process number
  2400                              <1>        		; clr *$ps / clear the status; process priority = 0
  2401                              <1> 	; 24/12/2021
  2402 00004899 75BA                <1> 	jnz	short sleep_3 ; jump to sysret
  2403                              <1>      ;1:
  2404 0000489B C3                  <1> 	retn
  2405                              <1> 		; rts r0 / return
  2406                              <1>      ;2:
  2407                              <1>         ;;jmp	sysret
  2408                              <1> 		; jmp sysret / return to user
  2409                              <1> 
  2410                              <1> isintr:
  2411                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2412                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2413                              <1> 	;
  2414                              <1> 	; 09/05/2013 - 30/05/2014
  2415                              <1> 	;
  2416                              <1> 	; Retro UNIX 8086 v1 modification !
  2417                              <1> 	; (Process/task switching and quit routine by using
  2418                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2419                              <1> 	;
  2420                              <1> 	; Retro UNIX 8086 v1 modification:
  2421                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2422                              <1> 	;  and there is a 'quit' request by user;
  2423                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2424                              <1> 	;  "nothing to do". (20/10/2013)
  2425                              <1> 	;
  2426                              <1> 	; 20/10/2013
  2427 0000489C 66833D[C8680000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2428 000048A4 761F                <1> 	jna	short isintr2 ; retn
  2429                              <1> 	; 03/09/2013
  2430                              <1> 	; (nothing to do)
  2431                              <1> 	;retn
  2432                              <1> 	; 22/09/2013
  2433 000048A6 66833D[DC680000]00  <1> 	cmp	word [u.intr], 0
  2434 000048AE 7615                <1> 	jna	short isintr2 ; retn
  2435                              <1> 	; 30/05/2014
  2436                              <1> 	;push	ax
  2437                              <1> 	; 24/12/2021
  2438 000048B0 50                  <1> 	push	eax
  2439 000048B1 66A1[DE680000]      <1> 	mov	ax, [u.quit]
  2440 000048B7 6609C0              <1> 	or	ax, ax ; 0 ?
  2441 000048BA 7408                <1> 	jz	short isintr1 ; zf = 1
  2442 000048BC 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2443 000048C0 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2444                              <1> 	;xor	ax, ax ; zf = 1
  2445                              <1> 	; 24/12/2021
  2446 000048C2 31C0                <1> 	xor	eax, eax ; zf = 1
  2447                              <1> isintr1:
  2448                              <1> 	;pop	ax
  2449                              <1> 	; 24/12/2021
  2450 000048C4 58                  <1> 	pop	eax
  2451                              <1> isintr2: ; 22/09/2013
  2452                              <1> 	; zf=1 -> nothing to do
  2453 000048C5 C3                  <1> 	retn
  2454                              <1> 
  2455                              <1> 	; UNIX v1 original 'isintr' routine... 
  2456                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2457                              <1>        	;mov     r2,-(sp) / save r2
  2458                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2459                              <1>         ;                 / typewriter
  2460                              <1>        	;beq     1f / if 0, do nothing except skip return
  2461                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2462                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2463                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2464                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2465                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2466                              <1>         ;              / of interrupts
  2467                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2468                              <1>      ;1:
  2469                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2470                              <1>      ;4:
  2471                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2472                              <1>        	;mov     (sp)+,r1
  2473                              <1>        	;rts     r0
  2474                              <1>      ;3: / interrupt char = quit (fs)
  2475                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2476                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2477                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2478                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2479                              <1>      ;1: / find process control tty entry in tty block
  2480                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2481                              <1>        	;beq     1f / block found go to 1f
  2482                              <1>        	;add     $8,r1 / look at next tty block
  2483                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2484                              <1>        	;blo     1b / no
  2485                              <1>        	;br      4b / no process control tty found so go to 4b
  2486                              <1>      ;1:
  2487                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2488                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2489                              <1>         ;                  / identifier
  2490                              <1>        	;inc     0f / increment
  2491                              <1>      ;1:
  2492                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2493                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2494                              <1>         ;             / being typed out after you hit the interrupt
  2495                              <1>         ;             / key
  2496                              <1>        	;br      1b
  2109                                  %include 'u5.s'        ; 03/06/2015
  2110                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS5.INC
  2111                              <1> ; Last Modification: 22/04/2022
  2112                              <1> ; ----------------------------------------------------------------------------
  2113                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2114                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2115                              <1> ;
  2116                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2117                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2118                              <1> ; <Bell Laboratories (17/3/1972)>
  2119                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2120                              <1> ;
  2121                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2122                              <1> ;
  2123                              <1> ; ****************************************************************************
  2124                              <1> 
  2125                              <1> mget:
  2126                              <1> 	; 22/04/2022
  2127                              <1> 	; 09/01/2022
  2128                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2129                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2130                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2131                              <1> 	;
  2132                              <1> 	; Get existing or (allocate) a new disk block for file
  2133                              <1> 	; 
  2134                              <1> 	; INPUTS ->
  2135                              <1> 	;    u.fofp (file offset pointer)
  2136                              <1> 	;    inode 
  2137                              <1> 	;    u.off (file offset)
  2138                              <1> 	; OUTPUTS ->
  2139                              <1> 	;    r1 (physical block number)
  2140                              <1> 	;    r2, r3, r5 (internal)
  2141                              <1> 	;
  2142                              <1> 	; ((AX = R1)) output
  2143                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2144                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2145                              <1> 
  2146                              <1> 		; mov *u.fofp,mq / file offset in mq
  2147                              <1> 		; clr ac / later to be high sig
  2148                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2149                              <1> 		; mov mq,r2
  2150                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2151                              <1> 		; bne 4f / branch for large file
  2152                              <1> mget_0:	
  2153                              <1> 	; 09/01/2022
  2154 000048C6 29C0                <1> 	sub	eax, eax
  2155 000048C8 29D2                <1> 	sub	edx, edx
  2156 000048CA 29C9                <1> 	sub	ecx, ecx
  2157 000048CC 29DB                <1> 	sub	ebx, ebx
  2158                              <1> 
  2159 000048CE 8B35[A8680000]      <1>         mov     esi, [u.fofp]
  2160                              <1>         ;movzx	ebx, byte [esi+1]
  2161                              <1> 	; 09/01/2022
  2162 000048D4 46                  <1> 	inc	esi
  2163 000048D5 8A1E                <1> 	mov	bl, [esi]
  2164                              <1> 
  2165                              <1> 	; BX = r2
  2166                              <1>         ; 24/12/2021
  2167 000048D7 F605[95650000]10    <1> 	test	byte [i.flgs+1], 10h
  2168                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2169                              <1> 				  ; is this a large or small file
  2170 000048DE 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2171                              <1> 
  2172 000048E0 F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2173                              <1> 		; bit $!17,r2
  2174 000048E3 7525                <1> 	jnz 	short mget_2
  2175                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2176 000048E5 80E30E              <1>         and     bl, 0Eh  
  2177                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2178                              <1> 	; 09/01/2021
  2179 000048E8 668B83[9A650000]    <1> 	mov	ax, [ebx+i.dskp]
  2180                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2181                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2182                              <1> 	; 24/12/2021
  2183 000048EF 09C0                <1> 	or	eax, eax
  2184                              <1> 	;or 	ax, ax
  2185 000048F1 7516                <1> 	jnz 	short mget_1 
  2186                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2187                              <1> 		       ; / for file
  2188 000048F3 E8A6000000          <1> 	call 	alloc
  2189                              <1> 		; jsr r0,alloc / allocate a new block
  2190                              <1>          ; eAX (r1) = Physical block number
  2191 000048F8 668983[9A650000]    <1> 	mov 	[ebx+i.dskp], ax
  2192                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2193 000048FF E835020000          <1> 	call 	setimod	
  2194                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2195 00004904 E8C2FEFFFF          <1> 	call	clear
  2196                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2197                              <1> mget_1: ; 2:
  2198                              <1>         ; eAX (r1) = Physical block number
  2199 00004909 C3                  <1> 	retn 
  2200                              <1> 		; rts r0
  2201                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2202 0000490A E88F000000          <1> 	call 	alloc
  2203                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2204                              <1> 	                     ; / block number in r1
  2205                              <1>         ; eAX (r1) = Physical block number
  2206 0000490F E85E0D0000          <1> 	call 	wslot
  2207                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2208                              <1> 			     ; / first data word in buffer
  2209                              <1>         ; eAX (r1) = Physical block number
  2210                              <1> 	; 09/01/2022
  2211 00004914 31C9                <1> 	xor	ecx, ecx
  2212 00004916 B108                <1> 	mov	cl, 8
  2213                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2214                              <1> 		   ; into new indirect block area for the new
  2215                              <1> 		   ; large file		
  2216 00004918 89DF                <1> 	mov 	edi, ebx ; r5
  2217 0000491A BE[9A650000]        <1> 	mov 	esi, i.dskp 
  2218                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2219                              <1> 			   ; / block pointers
  2220                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2221                              <1> 			  ; / large file
  2222                              <1> 	; 22/04/2022
  2223 0000491F 50                  <1> 	push	eax ; * ; bugfix
  2224                              <1> 
  2225                              <1> 	;xor 	ax, ax ; mov ax, 0
  2226                              <1> 	; 24/12/2021
  2227 00004920 31C0                <1> 	xor	eax, eax
  2228                              <1> mget_3: ;1:
  2229 00004922 66A5                <1> 	movsw
  2230                              <1> 		; mov (r2),(r5)+
  2231 00004924 668946FE            <1> 	mov 	[esi-2], ax
  2232                              <1> 		; clr (r2)+
  2233 00004928 E2F8                <1> 	loop	mget_3 ; 1b
  2234                              <1> 		; dec r3
  2235                              <1> 		; bgt 1b
  2236                              <1> 
  2237 0000492A B1F8                <1> 	mov 	cl, 256-8
  2238                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2239                              <1> mget_4:	; 1
  2240 0000492C F366AB              <1> 	rep 	stosw
  2241                              <1> 		; clr (r5)+
  2242                              <1> 		; dec r3
  2243                              <1> 		; bgt 1b
  2244                              <1> 
  2245                              <1> 	; 22/04/2022
  2246                              <1> 	;pop	eax ; * ; bugfix
  2247                              <1> 
  2248                              <1> 	; 24/03/2013
  2249                              <1>         ; AX (r1) = Physical block number
  2250 0000492F E85A0D0000          <1> 	call	dskwr
  2251                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2252                              <1> 
  2253                              <1> 	; 22/04/2022
  2254 00004934 58                  <1> 	pop	eax ; * ; bugfix
  2255                              <1> 
  2256                              <1>         ; eAX (r1) = Physical block number
  2257 00004935 66A3[9A650000]      <1> 	mov 	[i.dskp], ax
  2258                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2259                              <1> 	; 09/01/2022
  2260 0000493B 800D[95650000]10    <1> 	or	byte [i.flgs+1], 10h
  2261                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2262                              <1> 		; bis $10000,i.flgs / set large file bit 
  2263                              <1> 				  ; / in i.flgs word of i-node
  2264 00004942 E8F2010000          <1> 	call	setimod
  2265                              <1> 		; jsr r0,setimod / set i-node modified flag
  2266 00004947 E97AFFFFFF          <1>         jmp     mget_0 
  2267                              <1> 		; br mget
  2268                              <1> 
  2269                              <1> mget_5:  ; 4 ; large file
  2270                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2271                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2272                              <1> 			    ; / in indirect block
  2273                              <1> 		; mov r2,-(sp) / save on stack (*)
  2274                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2275                              <1>        		          ; / indirect block
  2276                              <1> 		; bic $!16,r2
  2277 0000494C 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2278 0000494F 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2279                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2280                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2281                              <1> 	; There is always 1 indirect block for this file system
  2282                              <1> 	; 09/01/2022
  2283 00004950 66A1[9A650000]      <1> 	mov	ax, [i.dskp]
  2284                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2285                              <1> 		; mov i.dskp(r2),r1
  2286                              <1> 	; 09/01/2022
  2287 00004956 09C0                <1> 	or	eax, eax
  2288                              <1> 	;or 	ax, ax ; R1
  2289 00004958 7515                <1> 	jnz 	short mget_6 ; 2f
  2290                              <1> 		; bne 2f / if no indirect block exists
  2291 0000495A E83F000000          <1> 	call 	alloc
  2292                              <1> 		; jsr r0,alloc / allocate a new block
  2293 0000495F 66A3[9A650000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2294                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2295 00004965 E8CF010000          <1> 	call 	setimod
  2296                              <1> 		; jsr r0,setimod / set i-node modified byte
  2297                              <1> 	; eAX = new block number
  2298 0000496A E85CFEFFFF          <1> 	call 	clear
  2299                              <1> 		; jsr r0,clear / clear new block
  2300                              <1> mget_6: ;2
  2301                              <1> 	; 05/03/2013
  2302                              <1> 	; eAX = r1, physical block number (of indirect block)
  2303 0000496F E88C0C0000          <1> 	call 	dskrd ; read indirect block
  2304                              <1> 		; jsr r0,dskrd / read in indirect block
  2305 00004974 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2306                              <1> 		; mov (sp)+,r2 / get offset
  2307                              <1> 	; eAX = r1, physical block number (of indirect block)
  2308 00004975 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2309                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2310                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2311 00004976 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2312                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2313                              <1> 	                  ; / points to location of inter
  2314                              <1> 	; 09/01/2022
  2315 00004978 668B03              <1> 	mov	ax, [ebx]
  2316                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2317                              <1> 			      ; in file sought in R1 (AX)
  2318                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2319                              <1> 	               	    ; / sought in r1
  2320                              <1> 	; 09/01/2022
  2321 0000497B 09C0                <1> 	or	eax, eax
  2322                              <1> 	;or 	ax, ax
  2323 0000497D 751D                <1>         jnz 	short mget_7 ; 2f
  2324                              <1> 		; bne 2f / if no block exists 
  2325 0000497F E81A000000          <1> 	call 	alloc
  2326                              <1> 		; jsr r0,alloc / allocate a new block
  2327 00004984 668903              <1> 	mov 	[ebx], ax ; R1
  2328                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2329                              <1> 	                    ; / indirect block
  2330 00004987 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2331                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2332 00004988 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2333 00004989 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2334 0000498A 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2335                              <1> 		; mov (r2),-(sp) / save block number of new block
  2336                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2337 0000498C E8E10C0000          <1> 	call 	wslot
  2338                              <1> 		; jsr r0,wslot
  2339                              <1>         ; eAX (r1) = physical block number
  2340                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2341 00004991 E8F80C0000          <1> 	call 	dskwr
  2342                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2343                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2344                              <1> 			     ; / back out on disk
  2345 00004996 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2346                              <1> 		; mov (sp),r1 / restore block number of new block	
  2347                              <1> 	; eAX (r1) = physical block number of new block
  2348 00004997 E82FFEFFFF          <1> 	call 	clear
  2349                              <1> 		; jsr r0,clear / clear new block	
  2350                              <1> mget_7: ; 2
  2351 0000499C 5A                  <1> 	pop 	edx ; **
  2352                              <1> 		; tst (sp)+ / bump stack pointer
  2353                              <1> 	; eAX (r1) = Block number of new block
  2354 0000499D C3                  <1> 	retn
  2355                              <1> 		; rts r0
  2356                              <1> 
  2357                              <1> alloc:
  2358                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2359                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2360                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2361                              <1> 	;
  2362                              <1> 	; get a free block and 
  2363                              <1> 	; set the corresponding bit in the free storage map
  2364                              <1> 	; 
  2365                              <1> 	; INPUTS ->
  2366                              <1> 	;    cdev (current device)
  2367                              <1> 	;    r2 
  2368                              <1> 	;    r3
  2369                              <1> 	; OUTPUTS ->
  2370                              <1> 	;    r1 (physical block number of block assigned)
  2371                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2372                              <1> 	;
  2373                              <1> 	; ((AX = R1)) output
  2374                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2375                              <1>         ;    ((Modified registers: DX, CX))  
  2376                              <1> 
  2377                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2378                              <1> 		;mov r3,-(sp)
  2379                              <1> 	;push 	ecx
  2380 0000499E 53                  <1> 	push 	ebx ; R2
  2381                              <1> 	;push 	edx ; R3
  2382 0000499F BB[58750000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2383                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2384 000049A4 803D[7B680000]00    <1> 	cmp 	byte [cdev], 0
  2385                              <1> 		; tst cdev
  2386 000049AB 7605                <1> 	jna	short alloc_1
  2387                              <1> 		; beq 1f / drum is device
  2388 000049AD BB[60770000]        <1> 	mov	ebx, mount
  2389                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2390                              <1> 			      ; / free storage map
  2391                              <1> alloc_1: ; 1
  2392                              <1> 	; 09/01/2022
  2393                              <1> 	;sub	ecx, ecx
  2394                              <1> 	;sub	edx, edx
  2395                              <1> 	;sub	eax, eax
  2396                              <1> 
  2397 000049B2 668B0B              <1>         mov	cx, [ebx]
  2398                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2399                              <1> 			     ; / storage map
  2400                              <1> 	; 09/01/2022
  2401 000049B5 C1E103              <1> 	shl	ecx, 3
  2402                              <1> 	;shl	cx, 3
  2403                              <1> 		; asl r1 / multiply r1 by eight gives 
  2404                              <1> 		; number of blocks in device
  2405                              <1> 		; asl r1
  2406                              <1> 		; asl r1
  2407                              <1> 	;;push	cx ;; 01/08/2013
  2408                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2409 000049B8 31C0                <1> 	xor 	eax, eax ; 0
  2410                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2411                              <1> alloc_2: ; 1
  2412 000049BA 43                  <1> 	inc 	ebx ; 18/8/2012
  2413 000049BB 43                  <1> 	inc 	ebx ; 
  2414 000049BC 668B13              <1> 	mov 	dx, [ebx]
  2415                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2416                              <1> 	; 09/01/2022
  2417 000049BF 09D2                <1> 	or	edx, edx
  2418                              <1> 	;or 	dx, dx
  2419 000049C1 750D                <1> 	jnz 	short alloc_3 ; 1f
  2420                              <1> 		; bne 1f / branch if any free blocks in this word	
  2421 000049C3 6683C010            <1> 	add 	ax, 16
  2422                              <1> 		; add $16.,r1
  2423                              <1> 	; 09/01/2022
  2424 000049C7 39C8                <1> 	cmp	eax, ecx
  2425                              <1> 	;cmp 	ax, cx    
  2426                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2427 000049C9 72EF                <1> 	jb 	short alloc_2
  2428                              <1> 		; blo 1b
  2429                              <1> 	; 14/11/2015
  2430                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2431                              <1> 	;	because of a (DMA or another) r/w error, 
  2432                              <1> 	;	we will be here, at 'jmp panic' code address,
  2433                              <1> 	;	even if the (disk) file system space is not full !!!
  2434                              <1> 	;	(cx = 0)	
  2435                              <1> 	;
  2436 000049CB E901E2FFFF          <1> 	jmp     panic 
  2437                              <1> 		; jmp panic / found no free storage
  2438                              <1> alloc_3: ; 1
  2439                              <1> 	; 09/01/2022
  2440 000049D0 D1EA                <1> 	shr	edx, 1
  2441                              <1> 	;shr	dx, 1
  2442                              <1> 		; asr r3 / find a free block
  2443 000049D2 7203                <1> 	jc	short alloc_4 ; 1f
  2444                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2445                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2446                              <1> 	; 09/01/2022
  2447 000049D4 40                  <1> 	inc	eax
  2448                              <1> 	;inc	ax
  2449                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2450 000049D5 EBF9                <1> 	jmp 	short alloc_3
  2451                              <1> 		; br 1b
  2452                              <1> alloc_4: ; 1:
  2453                              <1> 	;; pop cx ;; 01/08/2013
  2454                              <1> 		; tst (sp)+ / bump sp
  2455                              <1> 	; 02/04/2013 
  2456 000049D7 E829000000          <1> 	call	free3
  2457                              <1> 		; jsr r0,3f / have found a free block
  2458                              <1> 	; 21/8/2012
  2459 000049DC 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2460 000049DF 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2461                              <1> 		; bic r3,(r2) / set bit for this block 
  2462                              <1> 		            ; / i.e. assign block
  2463                              <1> 		; br 2f
  2464 000049E2 EB09                <1> 	jmp 	short alloc_5
  2465                              <1> 
  2466                              <1> free:
  2467                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2468                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2469                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2470                              <1> 	;
  2471                              <1> 	; calculates byte address and bit position for given block number
  2472                              <1> 	; then sets the corresponding bit in the free storage map
  2473                              <1> 	; 
  2474                              <1> 	; INPUTS ->
  2475                              <1> 	;    r1 - block number for a block structured device
  2476                              <1> 	;    cdev - current device 
  2477                              <1> 	; OUTPUTS ->
  2478                              <1> 	;    free storage map is updated
  2479                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2480                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2481                              <1> 	;
  2482                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2483                              <1>         ;  ((Modified registers: DX, CX))  
  2484                              <1> 
  2485                              <1> 		;mov r2,-(sp) / save r2, r3
  2486                              <1> 		;mov r3,-(sp)
  2487                              <1> 	;push 	ecx
  2488 000049E4 53                  <1> 	push 	ebx ; R2
  2489                              <1> 	;push 	edx ; R3 
  2490                              <1> 
  2491 000049E5 E81B000000          <1>         call    free3
  2492                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2493                              <1> 				 ; / in free storage map for block
  2494 000049EA 660913              <1> 	or 	[ebx], dx  
  2495                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2496                              <1> 			    ;  / indicates free block	
  2497                              <1> 	; 0 -> allocated, 1 -> free
  2498                              <1> 
  2499                              <1> alloc_5:
  2500                              <1> 	; 07/04/2013
  2501                              <1> free_1: ; 2:
  2502                              <1> 	;pop 	edx
  2503                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2504 000049ED 5B                  <1> 	pop	ebx
  2505                              <1> 		; mov (sp)+,r2
  2506                              <1> 	; pop	ecx
  2507 000049EE 803D[7B680000]00    <1> 	cmp 	byte [cdev], 0
  2508                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2509                              <1> 			 ; / cdev = 1, mountable device
  2510 000049F5 7707                <1> 	ja	short alloc_6 ; 1f
  2511                              <1> 		; bne 1f
  2512                              <1> 	;mov	byte [smod], 1
  2513 000049F7 FE05[8B680000]      <1> 	inc 	byte [smod]
  2514                              <1> 		; incb smod / set super block modified for drum
  2515                              <1> 	; eAX (r1) = block number
  2516 000049FD C3                  <1> 	retn
  2517                              <1> 		; rts r0
  2518                              <1> free_2:
  2519                              <1> alloc_6: ; 1:
  2520                              <1> 	;mov 	byte [mmod], 1
  2521 000049FE FE05[8C680000]      <1> 	inc 	byte [mmod]
  2522                              <1> 		; incb	mmod 
  2523                              <1> 		  ; / set super block modified for mountable device
  2524                              <1> 	; eAX (r1) = block number
  2525 00004A04 C3                  <1> 	retn	
  2526                              <1> 		; rts r0
  2527                              <1> free3:
  2528                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2529                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2530                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2531                              <1> 	;
  2532                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2533                              <1> 	; 
  2534                              <1> alloc_free_3: ; 3
  2535                              <1> 	;mov 	dx, 1
  2536                              <1> 	; 09/01/2022
  2537 00004A05 31D2                <1> 	xor	edx, edx
  2538 00004A07 42                  <1> 	inc	edx
  2539                              <1> 	; edx = 1
  2540 00004A08 88C1                <1> 	mov 	cl, al
  2541                              <1> 		; mov r1,r2 / block number, k, = 1		
  2542 00004A0A 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2543                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2544 00004A0D 7402                <1> 	jz 	short free4
  2545                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2546                              <1> 			       ; / (k) mod 8
  2547                              <1> 	;shl 	dx, cl
  2548                              <1> 	; 09/01/2022
  2549 00004A0F D3E2                <1> 	shl	edx, cl
  2550                              <1> free4:
  2551 00004A11 0FB7D8              <1> 	movzx 	ebx, ax
  2552                              <1> 		; mov r1,r2 / divide block number by 16
  2553                              <1> 	; 09/01/2022
  2554 00004A14 C1EB04              <1> 	shr	ebx, 4
  2555                              <1> 	;shr 	bx, 4
  2556                              <1> 		; asr r2
  2557                              <1> 		; asr r2
  2558                              <1> 		; asr r2
  2559                              <1> 		; asr r2
  2560                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2561                              <1> 		       ; / bit for block is in lower half of word
  2562                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2563                              <1> 		        ; / storage map
  2564                              <1> alloc_free_4: ; 1
  2565                              <1> 	; 09/01/2022
  2566 00004A17 D1E3                <1> 	shl	ebx, 1
  2567                              <1> 	;shl 	bx, 1
  2568                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2569 00004A19 81C3[5A750000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2570                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2571                              <1> 	    		        ; / with block bit in it 	
  2572 00004A1F 803D[7B680000]00    <1> 	cmp	byte [cdev], 0
  2573                              <1> 		; tst cdev
  2574 00004A26 7606                <1> 	jna	short alloc_free_5
  2575                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2576 00004A28 81C308020000        <1> 	add	ebx, mount - systm
  2577                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2578                              <1> 				    ; / mountable device with bit of block to be
  2579                              <1> 				    ; / freed
  2580                              <1> alloc_free_5: ; 1 
  2581 00004A2E C3                  <1> 	retn
  2582                              <1> 		; rts r0 / return to 'free'
  2583                              <1> 	      ; 2
  2584                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2585                              <1> 	
  2586                              <1> iget:
  2587                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2588                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2589                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2590                              <1> 	;
  2591                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2592                              <1> 	;
  2593                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2594                              <1> 	; 
  2595                              <1> 	; INPUTS ->
  2596                              <1> 	;    ii - current i-number, rootdir
  2597                              <1> 	;    cdev - new i-node device
  2598                              <1> 	;    idev - current i-node device
  2599                              <1> 	;    imod - current i-node modified flag
  2600                              <1> 	;    mnti - cross device file i-number
  2601                              <1> 	;    r1 - i-numbe rof new i-node
  2602                              <1> 	;    mntd - mountable device number		
  2603                              <1> 	; 	 
  2604                              <1> 	; OUTPUTS ->
  2605                              <1> 	;    cdev, idev, imod, ii, r1
  2606                              <1> 	;
  2607                              <1> 	; ((AX = R1)) input/output
  2608                              <1> 	;
  2609                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2610                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2611                              <1> 
  2612 00004A2F 8A15[7B680000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2613 00004A35 8A35[7A680000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2614                              <1> 	;
  2615 00004A3B 663B05[78680000]    <1> 	cmp 	ax, [ii]
  2616                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2617 00004A42 7504                <1> 	jne 	short iget_1
  2618                              <1> 		; bne 1f
  2619 00004A44 38F2                <1> 	cmp	dl, dh
  2620                              <1> 		; cmp idev,cdev
  2621                              <1> 			  ; / is device number of i-node = current device
  2622 00004A46 7472                <1>         je      short iget_5
  2623                              <1> 		; beq 2f
  2624                              <1> iget_1: ; 1:
  2625 00004A48 30DB                <1> 	xor	bl, bl
  2626 00004A4A 381D[8A680000]      <1> 	cmp	[imod], bl ; 0	
  2627                              <1> 		; tstb imod / has i-node of current file
  2628                              <1> 			  ; / been modified i.e., imod set
  2629 00004A50 7629                <1> 	jna	short iget_2
  2630                              <1> 		; beq 1f
  2631 00004A52 881D[8A680000]      <1> 	mov	[imod], bl ; 0
  2632                              <1> 		;  clrb	imod / if it has, 
  2633                              <1> 			   ; / we must write the new i-node out on disk
  2634                              <1> 	; 24/12/2021
  2635 00004A58 50                  <1> 	push	eax ; *
  2636                              <1> 	;push	ax
  2637                              <1> 		; mov r1,-(sp)
  2638                              <1> 	;mov	dl, [cdev]
  2639 00004A59 52                  <1> 	push	edx ; **
  2640                              <1> 	;push	dx
  2641                              <1> 		; mov cdev,-(sp)
  2642 00004A5A 66A1[78680000]      <1> 	mov	ax, [ii]
  2643                              <1> 		; mov ii,r1
  2644                              <1> 	;mov	dh, [idev]
  2645 00004A60 8835[7B680000]      <1> 	mov	[cdev], dh
  2646                              <1> 		; mov idev,cdev
  2647 00004A66 FEC3                <1> 	inc	bl ; 1
  2648                              <1> 	; 31/07/2013
  2649 00004A68 881D[1C690000]      <1> 	mov     [rw], bl ; 1 == write 
  2650                              <1> 	;;28/07/2013 rw -> u.rw
  2651                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2652 00004A6E E848000000          <1> 	call	icalc
  2653                              <1> 		; jsr r0,icalc; 1
  2654                              <1> 	;pop	dx
  2655                              <1> 	; 24/12/2021
  2656 00004A73 5A                  <1> 	pop	edx ; **
  2657 00004A74 8815[7B680000]      <1> 	mov	[cdev], dl
  2658                              <1> 		; mov (sp)+,cdev
  2659                              <1> 	; 24/12/2021
  2660 00004A7A 58                  <1> 	pop	eax ; *
  2661                              <1> 	;pop	ax
  2662                              <1> 		; mov (sp)+,r1
  2663                              <1> iget_2: ; 1:
  2664 00004A7B 6621C0              <1> 	and	ax, ax
  2665                              <1> 		; tst r1 / is new i-number non zero
  2666 00004A7E 7434                <1> 	jz	short iget_4 ; 2f
  2667                              <1> 		; beq 2f / branch if r1=0
  2668                              <1> 
  2669                              <1> 	;mov 	dl, [cdev]
  2670 00004A80 08D2                <1> 	or	dl, dl
  2671                              <1> 		; tst cdev / is the current device number non zero
  2672                              <1> 			 ; / (i.e., device =/ drum)
  2673 00004A82 7517                <1> 	jnz	short iget_3 ;  1f
  2674                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2675 00004A84 663B05[80680000]    <1> 	cmp	ax, [mnti]			
  2676                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2677                              <1> 			    ; / file (root directory of mounted device)
  2678 00004A8B 750E                <1> 	jne	short iget_3 ; 1f
  2679                              <1> 		; bne 1f
  2680                              <1>         ;mov    bl, [mntd]
  2681 00004A8D FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2682 00004A8F 8815[7B680000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2683                              <1> 		; mov mntd,cdev / make mounted device the current device
  2684 00004A95 66A1[86680000]      <1> 	mov	ax, [rootdir]
  2685                              <1> 		; mov rootdir,r1
  2686                              <1> iget_3: ; 1:
  2687 00004A9B 66A3[78680000]      <1> 	mov	[ii], ax
  2688                              <1> 		; mov r1,ii
  2689 00004AA1 8815[7A680000]      <1> 	mov	[idev], dl ; cdev
  2690                              <1> 		; mov cdev,idev
  2691 00004AA7 30DB                <1> 	xor	bl, bl
  2692                              <1>         ; 31/07/2013
  2693 00004AA9 881D[1C690000]      <1> 	mov     [rw], bl ; 0 == read 
  2694                              <1> 	;;28/07/2013 rw -> u.rw       
  2695                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2696 00004AAF E807000000          <1> 	call	icalc
  2697                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2698                              <1> iget_4: ; 2:
  2699 00004AB4 66A1[78680000]      <1> 	mov	ax, [ii]
  2700                              <1> 		; mov ii,r1
  2701                              <1> iget_5:
  2702 00004ABA C3                  <1> 	retn
  2703                              <1> 		; rts r0
  2704                              <1> 
  2705                              <1> icalc:
  2706                              <1> 	; 04/04/2022 (47->31)
  2707                              <1> 	;	(Inode Table/List Address modification)
  2708                              <1> 	; 09/01/2022
  2709                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2710                              <1> 	; 02/07/2015
  2711                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2712                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2713                              <1> 	;
  2714                              <1> 	; calculate physical block number from i-number then
  2715                              <1> 	; read or write that block
  2716                              <1> 	;
  2717                              <1> 	; 'icalc' is called from 'iget'
  2718                              <1> 	;
  2719                              <1> 	; for original unix v1:
  2720                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2721                              <1>        	; / (i+31.) mod 16. bytes from its start
  2722                              <1> 	;
  2723                              <1> 	; for retro unix 8086 v1:
  2724                              <1> 	;  i-node is located in block (i+47)/16 and
  2725                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2726                              <1> 	;
  2727                              <1> 	; INPUTS ->
  2728                              <1> 	;    r1 - i-number of i-node
  2729                              <1> 	; 	 
  2730                              <1> 	; OUTPUTS ->
  2731                              <1> 	;    inode r/w
  2732                              <1> 	;
  2733                              <1> 	; ((AX = R1)) input
  2734                              <1> 	;
  2735                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2736                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2737                              <1> 	;
  2738 00004ABB 0FB7D0              <1> 	movzx	edx, ax	
  2739                              <1> 	;add	dx, 47
  2740                              <1> 	; 04/04/2022
  2741 00004ABE 6683C21F            <1> 	add	dx, 31
  2742 00004AC2 89D0                <1> 	mov	eax, edx
  2743                              <1> 	;;add	ax, 47	; add 47 to inode number
  2744                              <1> 	;add	ax, 31
  2745                              <1> 		; add $31.,r1 / add 31. to i-number
  2746 00004AC4 50                  <1> 	push	eax
  2747                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2748                              <1> 	; 09/01/2022
  2749 00004AC5 C1E804              <1> 	shr	eax, 4
  2750                              <1> 	;shr 	ax, 4
  2751                              <1> 		; asr r1 / divide by 16.
  2752                              <1> 		; asr r1
  2753                              <1> 		; asr r1
  2754                              <1> 		; asr r1 / r1 contains block number of block
  2755                              <1> 		       ; / in which i-node exists
  2756 00004AC8 E8330B0000          <1> 	call	dskrd
  2757                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2758                              <1> 	; 31/07/2013
  2759 00004ACD 803D[1C690000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2760                              <1> 	;; 28/07/2013 rw -> u.rw
  2761                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2762                              <1> 		; tst (r0)
  2763 00004AD4 7605                <1> 	jna	short icalc_1
  2764                              <1> 		; beq 1f / branch to wslot when argument
  2765                              <1> 		       ; / in icalc call = 1
  2766                              <1> 	; eAX = r1 = block number
  2767 00004AD6 E8970B0000          <1> 	call	wslot
  2768                              <1> 		; jsr r0,wslot / set up data buffer for write
  2769                              <1> 			     ; / (will be same buffer as dskrd got)
  2770                              <1> 	; eBX = r5 points to first word in data area for this block
  2771                              <1> icalc_1: ; 1:
  2772 00004ADB 5A                  <1> 	pop	edx 
  2773 00004ADC 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2774                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2775                              <1> 			      ; / gives (i+31.) mod 16
  2776 00004ADF C1E205              <1> 	shl 	edx, 5
  2777                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2778 00004AE2 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2779 00004AE4 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2780                              <1>           	; eSI (r5) points to first word in i-node i.	
  2781                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2782                              <1> 			     ; / 32.*(i+31.)mod16
  2783                              <1> 		; mov $5,lsh / for i-node i.
  2784                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2785 00004AE6 BF[94650000]        <1> 	mov	edi, inode
  2786                              <1> 		; mov $inode,r1 / inode is address of first word 
  2787                              <1> 			      ; / of current i-node
  2788                              <1> 	; 09/01/2022
  2789 00004AEB 29C9                <1> 	sub	ecx, ecx
  2790 00004AED B108                <1> 	mov	cl, 8 
  2791                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2792                              <1> 		; mov $16.,r3
  2793                              <1>        ; 31/07/2013
  2794 00004AEF 382D[1C690000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2795                              <1>        ;;28/07/2013 rw -> u.rw                 
  2796                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2797                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2798 00004AF5 7609                <1> 	jna	short icalc_3
  2799                              <1> 		; beq 2f / r0 now contains proper return address 
  2800                              <1> 		       ; / for rts r0
  2801                              <1> icalc_2: ; 1:
  2802 00004AF7 87F7                <1> 	xchg 	esi, edi
  2803                              <1> 	; overwrite old i-node (in buffer to be written)
  2804 00004AF9 F3A5                <1> 	rep 	movsd
  2805                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2806                              <1> 		; dec r3
  2807                              <1> 		; bgt 1b
  2808                              <1> 	;call	dskwr
  2809                              <1> 		; jsr r0,dskwr / write inode out on device
  2810                              <1> 	;retn
  2811                              <1> 		; rts r0
  2812                              <1> 	; 24/12/2021
  2813 00004AFB E98E0B0000          <1> 	jmp	dskwr
  2814                              <1> 
  2815                              <1> icalc_3: ; 2:
  2816                              <1> 	; copy new i-node into inode area of (core) memory
  2817 00004B00 F3A5                <1> 	rep 	movsd
  2818                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2819                              <1> 		                ; / "inode" area of core
  2820                              <1> 		; dec r3
  2821                              <1> 		; bgt 2b
  2822 00004B02 C3                  <1> 	retn
  2823                              <1> 		; rts r0
  2824                              <1> 
  2825                              <1> access:
  2826                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2827                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2828                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2829                              <1> 	;
  2830                              <1> 	; check whether user is owner of file or user has read or write
  2831                              <1> 	; permission (based on i.flgs).
  2832                              <1> 	;
  2833                              <1> 	; INPUTS ->
  2834                              <1> 	;    r1 - i-number of file
  2835                              <1> 	;    u.uid
  2836                              <1> 	; arg0 -> (owner flag mask)	 		
  2837                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2838                              <1> 	; OUTPUTS ->
  2839                              <1> 	;    inode (or jump to error)
  2840                              <1> 	;
  2841                              <1> 	; ((AX = R1)) input/output
  2842                              <1> 	;
  2843                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2844                              <1> 	
  2845                              <1> 	;push	dx  ; save flags (DL)
  2846                              <1> 	; 24/12/2021
  2847 00004B03 52                  <1> 	push	edx ; save flags (DL)
  2848 00004B04 E826FFFFFF          <1> 	call	iget
  2849                              <1> 		; jsr r0,iget / read in i-node for current directory
  2850                              <1> 			    ; / (i-number passed in r1)
  2851 00004B09 8A0D[94650000]      <1> 	mov	cl, [i.flgs]
  2852                              <1> 		; mov i.flgs,r2
  2853                              <1> 	; 24/12/2021
  2854 00004B0F 5A                  <1> 	pop	edx ; restore flags (DL)
  2855                              <1> 	;pop	dx  ; restore flags (DL)
  2856 00004B10 8A35[E4680000]      <1> 	mov	dh, [u.uid]
  2857 00004B16 3A35[97650000]      <1> 	cmp	dh, [i.uid]
  2858                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2859 00004B1C 7503                <1> 	jne	short access_1
  2860                              <1> 		; bne 1f / no, then branch
  2861 00004B1E C0E902              <1> 	shr	cl, 2
  2862                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2863                              <1> 		        ; / read/write bits
  2864                              <1> 		; asrb r2
  2865                              <1> access_1: ; 1:
  2866 00004B21 20D1                <1> 	and	cl, dl
  2867                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2868                              <1> 			     ; / in access call
  2869 00004B23 7513                <1> 	jnz	short access_2
  2870                              <1> 		; bne 1f
  2871 00004B25 08F6                <1> 	or	dh, dh	; super user (root) ?
  2872                              <1> 		; tstb u.uid
  2873 00004B27 740F                <1> 	jz	short access_2 ; yes, super user
  2874                              <1> 	;jnz	error
  2875                              <1> 		; beq 1f
  2876                              <1> 		; jmp error
  2877 00004B29 C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2877 00004B31 0000                <1>
  2878                              <1> 			; 'permission denied !' error
  2879 00004B33 E9DAE7FFFF          <1> 	jmp	error
  2880                              <1> 
  2881                              <1> access_2: ; 1:
  2882                              <1> 	; DL = flags
  2883 00004B38 C3                  <1> 	retn
  2884                              <1> 		; rts r0
  2885                              <1> 
  2886                              <1> setimod:
  2887                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2888                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2889                              <1> 	;
  2890                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2891                              <1> 	; the inode has been modified. Also puts the time of modification
  2892                              <1> 	; into the inode.
  2893                              <1> 	;
  2894                              <1> 	; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2895                              <1>         ; ((Modified registers: eDX, eCX, eBX)) 
  2896                              <1> 	;
  2897                              <1> 	
  2898                              <1> 	;push 	edx
  2899 00004B39 50                  <1> 	push	eax
  2900                              <1> 
  2901 00004B3A C605[8A680000]01    <1> 	mov 	byte [imod], 1
  2902                              <1> 		; movb $1,imod / set current i-node modified bytes
  2903                              <1> 	; Erdogan Tan 14-7-2012
  2904 00004B41 E81AE3FFFF          <1> 	call 	epoch
  2905                              <1> 		 ; mov s.time,i.mtim 
  2906                              <1> 			    ; / put present time into file modified time
  2907                              <1> 		 ; mov s.time+2,i.mtim+2
  2908                              <1> 
  2909 00004B46 A3[AE650000]        <1> 	mov 	[i.mtim], eax
  2910                              <1> 	
  2911                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2912                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2913 00004B4B 833D[AA650000]00    <1> 	cmp	dword [i.ctim], 0
  2914 00004B52 7505                <1> 	jnz	short setimod_ok
  2915                              <1> 
  2916 00004B54 A3[AA650000]        <1> 	mov 	[i.ctim], eax
  2917                              <1> 
  2918                              <1> setimod_ok: ; 31/07/2013
  2919 00004B59 58                  <1> 	pop	eax
  2920                              <1> 	;pop	edx
  2921                              <1> 	
  2922 00004B5A C3                  <1> 	retn
  2923                              <1> 		; rts r0
  2924                              <1> 
  2925                              <1> itrunc:
  2926                              <1> 	; 03/02/2022
  2927                              <1> 	; 09/01/2022
  2928                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1) 
  2929                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2930                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2931                              <1> 	;
  2932                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2933                              <1> 	;  to zero length.
  2934                              <1> 	;
  2935                              <1> 	; INPUTS ->
  2936                              <1> 	;    r1 - i-number of i-node
  2937                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2938                              <1> 	;    i.flgs - large file flag		
  2939                              <1> 	;    i.size - size of file	
  2940                              <1> 	; 	 
  2941                              <1> 	; OUTPUTS ->
  2942                              <1> 	;    i.flgs - large file flag is cleared
  2943                              <1> 	;    i.size - set to 0	
  2944                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2945                              <1> 	;    setimod - set to indicate i-node has been modified
  2946                              <1> 	;    r1 - i-number of i-node  					
  2947                              <1> 	;
  2948                              <1> 	; ((AX = R1)) input/output
  2949                              <1> 	;
  2950                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2951                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2952                              <1> 
  2953 00004B5B E8CFFEFFFF          <1> 	call	iget
  2954                              <1> 		; jsr r0,iget
  2955 00004B60 BE[9A650000]        <1> 	mov	esi, i.dskp
  2956                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2957 00004B65 31C0                <1> 	xor	eax, eax
  2958                              <1> itrunc_1: ; 1:
  2959 00004B67 66AD                <1> 	lodsw
  2960                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2961                              <1> 	; 09/01/2022
  2962 00004B69 09C0                <1> 	or	eax, eax
  2963                              <1> 	;or 	ax, ax
  2964 00004B6B 7433                <1> 	jz	short itrunc_5
  2965                              <1> 		; beq 5f
  2966 00004B6D 56                  <1> 	push	esi
  2967                              <1> 		; mov r2,-(sp)
  2968                              <1> 	; 09/01/2022
  2969 00004B6E F605[95650000]10    <1> 	test	byte [i.flgs+1], 10h
  2970                              <1> 	;test	word [i.flgs], 1000h
  2971                              <1> 		; bit $10000,i.flgs / test large file bit?
  2972 00004B75 7423                <1> 	jz	short itrunc_4
  2973                              <1> 		; beq 4f / if clear, branch
  2974 00004B77 50                  <1> 	push	eax
  2975                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2976 00004B78 E8830A0000          <1> 	call	dskrd
  2977                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2978                              <1> 			     ; / pointed to by r5
  2979                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2980                              <1> 	; 09/01/2022
  2981 00004B7D 31C9                <1> 	xor	ecx, ecx
  2982 00004B7F FEC5                <1> 	inc	ch ; mov ch, 1
  2983                              <1> 	; ecx = 256
  2984                              <1> 	;mov	ecx, 256
  2985                              <1> 		; mov $256.,r3 / move word count into r3
  2986 00004B81 89DE                <1> 	mov	esi, ebx
  2987                              <1> itrunc_2: ; 2:
  2988 00004B83 66AD                <1> 	lodsw
  2989                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2990                              <1> 			     ; / physical block number
  2991                              <1> 	; 09/01/2022
  2992 00004B85 21C0                <1> 	and	eax, eax
  2993                              <1> 	;and	ax, ax
  2994 00004B87 7407                <1> 	jz	short itrunc_3
  2995                              <1> 		; beq 3f / branch if zero
  2996                              <1> 	; 24/12/2021
  2997 00004B89 51                  <1> 	push	ecx
  2998                              <1> 	;push	cx
  2999                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  3000                              <1> 	;push	esi
  3001                              <1> 		; mov r5,-(sp)
  3002 00004B8A E855FEFFFF          <1> 	call	free
  3003                              <1> 		; jsr r0,free / free block in free storage map
  3004                              <1> 	;pop	esi
  3005                              <1> 		; mov(sp)+,r5
  3006                              <1> 	;pop	cx
  3007 00004B8F 59                  <1> 	pop	ecx
  3008                              <1> 		; mov (sp)+,r3
  3009                              <1> itrunc_3: ; 3:
  3010 00004B90 E2F1                <1> 	loop	itrunc_2
  3011                              <1> 		; dec r3 / decrement word count
  3012                              <1> 		; bgt 2b / branch if positive
  3013 00004B92 58                  <1> 	pop	eax
  3014                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3015                              <1> 			     ; / indirect block
  3016                              <1> 	; 01/08/2013
  3017                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3018                              <1> 	; 03/02/2022
  3019 00004B93 8025[95650000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  3020                              <1> itrunc_4: ; 4:
  3021 00004B9A E845FEFFFF          <1> 	call	free
  3022                              <1> 		; jsr r0,free / free indirect block
  3023 00004B9F 5E                  <1> 	pop	esi
  3024                              <1> 		; mov (sp)+,r2
  3025                              <1> itrunc_5: ; 5:
  3026 00004BA0 81FE[AA650000]      <1> 	cmp	esi, i.dskp+16
  3027                              <1> 		; cmp r2,$i.dskp+16.
  3028 00004BA6 72BF                <1> 	jb	short itrunc_1	
  3029                              <1> 		; bne 1b / branch until all i.dskp entries check
  3030                              <1> 	; 03/02/2022
  3031                              <1> 	;and	byte [i.flgs+1], 0EFh
  3032                              <1> 	; 01/08/2013
  3033                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3034                              <1> 		; bic $10000,i.flgs / clear large file bit
  3035 00004BA8 BF[9A650000]        <1> 	mov	edi, i.dskp
  3036                              <1> 	;mov	cx, 8
  3037                              <1> 	;xor 	ax, ax
  3038                              <1> 	; 09/01/2022
  3039 00004BAD 29C9                <1> 	sub	ecx, ecx
  3040 00004BAF B108                <1> 	mov	cl, 8
  3041 00004BB1 29C0                <1> 	sub	eax, eax
  3042 00004BB3 66A3[98650000]      <1> 	mov	[i.size], ax ; 0
  3043                              <1> 		; clr i.size / zero file size
  3044 00004BB9 F366AB              <1> 	rep	stosw
  3045                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3046                              <1> 			   ; / zero block pointers
  3047 00004BBC E878FFFFFF          <1> 	call	setimod
  3048                              <1> 		; jsr r0,setimod / set i-node modified flag
  3049 00004BC1 66A1[78680000]      <1> 	mov	ax, [ii]
  3050                              <1> 		; mov ii,r1
  3051 00004BC7 C3                  <1> 	retn
  3052                              <1> 		; rts r0
  3053                              <1> 
  3054                              <1> imap:
  3055                              <1> 	; 11/02/2022
  3056                              <1> 	; 03/02/2022
  3057                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3058                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3059                              <1> 	;
  3060                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3061                              <1> 	; allocation bit for an i-node whose number in r1.
  3062                              <1> 	;
  3063                              <1> 	; INPUTS ->
  3064                              <1> 	;    r1 - contains an i-number
  3065                              <1> 	;    fsp - start of table containing open files
  3066                              <1> 	;
  3067                              <1> 	; OUTPUTS ->
  3068                              <1> 	;    r2 - byte address of byte with the allocation bit
  3069                              <1> 	;    mq - a mask to locate the bit position.	
  3070                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3071                              <1> 	;
  3072                              <1> 	; ((AX = R1)) input/output
  3073                              <1> 	; ((DL/DX = MQ)) output
  3074                              <1> 	; ((BX = R2)) output
  3075                              <1> 	;
  3076                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3077                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3078                              <1> 	;
  3079                              <1> 		; / get the byte that has the allocation bit for 
  3080                              <1> 		; / the i-number contained in r1
  3081                              <1> 	;mov	dx, 1
  3082 00004BC8 B201                <1> 	mov	dl, 1
  3083                              <1> 		; mov $1,mq / put 1 in the mq
  3084 00004BCA 0FB7D8              <1> 	movzx	ebx, ax
  3085                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3086                              <1>  		          ; / in the map we must find
  3087 00004BCD 6683EB29            <1> 	sub	bx, 41
  3088                              <1> 		; sub $41.,r2 / r2 has i-41
  3089 00004BD1 88D9                <1> 	mov	cl, bl
  3090                              <1> 		; mov r2,r3 / r3 has i-41
  3091 00004BD3 80E107              <1> 	and	cl, 7
  3092                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3093                              <1> 			   ; / the bit position
  3094 00004BD6 7402                <1> 	jz	short imap1
  3095                              <1> 	;shl	dx, cl
  3096 00004BD8 D2E2                <1> 	shl	dl, cl
  3097                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3098                              <1> imap1:			   ; / to the left to mask the correct bit
  3099                              <1> 	; 03/02/2022
  3100 00004BDA C1EB03              <1> 	shr	ebx, 3
  3101                              <1> 	;shr	bx, 3
  3102                              <1> 		; asr r2
  3103                              <1> 		; asr r2
  3104                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3105                              <1> 		       ; / from the start of the map
  3106                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3107 00004BDD BE[58750000]        <1> 	mov	esi, systm
  3108                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3109                              <1> 				; / the super block for drum
  3110                              <1> 	;cmp	word [cdev], 0
  3111 00004BE2 803D[7B680000]00    <1> 	cmp	byte [cdev], 0
  3112                              <1> 		; tst cdev / is the device the disk
  3113 00004BE9 7606                <1> 	jna	short imap2
  3114                              <1> 		; beq 1f / yes
  3115 00004BEB 81C608020000        <1> 	add	esi, mount - systm
  3116                              <1> 		; add $mount-systm,r2 / for mounted device,
  3117                              <1> 			; / r2 points to 1st word of its super block
  3118                              <1> imap2: ; 1:
  3119 00004BF1 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3120                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3121 00004BF4 6683C304            <1> 	add	bx, 4
  3122 00004BF8 01F3                <1> 	add	ebx, esi
  3123                              <1>         	; add (sp)+,r2 / ?
  3124                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3125                              <1> 		      ;; (2 + free map size + 2)
  3126                              <1> 		; add $2,r2 / ?
  3127                              <1> 
  3128                              <1> 	; 11/02/2022
  3129 00004BFA 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3130 00004C00 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3131                              <1> 			  ; if inode num overs inode count
  3132                              <1> 
  3133                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3134                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3135                              <1> 
  3136                              <1> 	; 11/02/2022
  3137                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3138                              <1> 	;	(number of requested inode > inode count)
  3139                              <1> 
  3140 00004C02 C3                  <1> 	retn
  3141                              <1> 		; rts r0
  2110                                  %include 'u6.s'        ; 31/05/2015
  2111                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS6.INC
  2112                              <1> ; Last Modification: 13/06/2022
  2113                              <1> ; ----------------------------------------------------------------------------
  2114                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2115                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2116                              <1> ;
  2117                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2118                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2119                              <1> ; <Bell Laboratories (17/3/1972)>
  2120                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2121                              <1> ;
  2122                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2123                              <1> ;
  2124                              <1> ; ****************************************************************************
  2125                              <1> 
  2126                              <1> readi:
  2127                              <1> 	; 11/01/2022
  2128                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2129                              <1> 	; 20/05/2015
  2130                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2131                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2132                              <1> 	;
  2133                              <1> 	; Reads from an inode whose number in R1
  2134                              <1> 	; 
  2135                              <1> 	; INPUTS ->
  2136                              <1> 	;    r1 - inode number
  2137                              <1> 	;    u.count - byte count user desires
  2138                              <1> 	;    u.base - points to user buffer
  2139                              <1> 	;    u.fofp - points to word with current file offset
  2140                              <1> 	; OUTPUTS ->
  2141                              <1> 	;    u.count - cleared
  2142                              <1> 	;    u.nread - accumulates total bytes passed back
  2143                              <1> 	;
  2144                              <1> 	; ((AX = R1)) input/output
  2145                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2146                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2147                              <1> 
  2148 00004C03 31D2                <1> 	xor	edx, edx ; 0
  2149 00004C05 8915[C0680000]      <1> 	mov 	[u.nread], edx ; 0
  2150                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2151 00004C0B 668915[FD680000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2152 00004C12 3915[BC680000]      <1> 	cmp 	[u.count], edx ; 0
  2153                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2154 00004C18 7701                <1> 	ja 	short readi_1 ; 1f
  2155                              <1> 		 ; bgt 1f / yes, branch
  2156 00004C1A C3                  <1> 	retn
  2157                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2158                              <1> readi_1: ; 1:
  2159                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2160 00004C1B 6683F828            <1> 	cmp	ax, 40
  2161                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2162                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2163                              <1>         ;ja	dskr 
  2164                              <1> 		 ; ble 1f / yes, branch
  2165                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2166                              <1> 		 ;         / read file with i-node number (r1)
  2167                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2168                              <1> 	; 24/12/2021
  2169 00004C1F 7605                <1> 	jna	short readi_3
  2170 00004C21 E9CF000000          <1> 	jmp	dskr
  2171                              <1> readi_3:
  2172                              <1> 	; (20/05/2015)
  2173 00004C26 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2174                              <1> 	; 1:
  2175 00004C27 0FB6D8              <1> 	movzx	ebx, al
  2176                              <1> 	; 11/01/2022
  2177 00004C2A C1E302              <1> 	shl	ebx, 2
  2178                              <1> 	;shl	bx, 2
  2179                              <1> 		 ; asl r1 / multiply inode number by 2
  2180 00004C2D 81C3[314C0000]      <1> 	add	ebx, readi_2 - 4
  2181 00004C33 FF23                <1> 	jmp	dword [ebx]	
  2182                              <1> 		 ; jmp *1f-2(r1)
  2183                              <1> readi_2: ; 1:
  2184 00004C35 [814C0000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2185                              <1> 		 ;rtty / tty; r1=2
  2186                              <1> 		 ;rppt / ppt; r1=4
  2187 00004C39 [D14C0000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2188                              <1> 		 ;rmem / mem; r1=6
  2189                              <1> 		 ;rrf0 / rf0
  2190                              <1> 		 ;rrk0 / rk0
  2191                              <1> 		 ;rtap / tap0
  2192                              <1> 		 ;rtap / tap1
  2193                              <1> 		 ;rtap / tap2
  2194                              <1> 		 ;rtap / tap3
  2195                              <1> 		 ;rtap / tap4
  2196                              <1> 		 ;rtap / tap5
  2197                              <1> 		 ;rtap / tap6
  2198                              <1> 		 ;rtap / tap7
  2199 00004C3D [B1540000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2200 00004C41 [B1540000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2201 00004C45 [B1540000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2202 00004C49 [B1540000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2203 00004C4D [B1540000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2204 00004C51 [B1540000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2205 00004C55 [E64C0000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2206 00004C59 [CD4C0000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2207                              <1> 		 ;rcvt / tty0
  2208 00004C5D [CD4C0000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2209                              <1> 		 ;rcvt / tty1
  2210 00004C61 [CD4C0000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2211                              <1> 		 ;rcvt / tty2
  2212 00004C65 [CD4C0000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2213                              <1> 		 ;rcvt / tty3
  2214 00004C69 [CD4C0000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2215                              <1> 		 ;rcvt / tty4
  2216 00004C6D [CD4C0000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2217                              <1> 		 ;rcvt / tty5
  2218 00004C71 [CD4C0000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2219                              <1> 		 ;rcvt / tty6
  2220 00004C75 [CD4C0000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2221                              <1> 		 ;rcvt / tty7
  2222 00004C79 [CD4C0000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2223                              <1> 		 ;rcrd / crd
  2224 00004C7D [CD4C0000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2225                              <1> 
  2226                              <1> rtty: ; / read from console tty
  2227                              <1> 	; 11/01/2022
  2228                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2229                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2230                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2231                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2232                              <1> 	;	     must be written immediate on video page (screen)
  2233                              <1> 	;	     when it is required.	
  2234                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2235                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2236                              <1> 	;
  2237                              <1> 	; Console tty buffer is PC keyboard buffer
  2238                              <1> 	; and keyboard-keystroke handling is different than original
  2239                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2240                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2241                              <1> 	;
  2242                              <1> 	; 06/12/2013
  2243 00004C81 0FB61D[E7680000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2244 00004C88 8A83[F3650000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2245                              <1> rttys:
  2246                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2247                              <1> 	               ; / of the control and status block
  2248                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2249                              <1> 		       ; / tty buffer
  2250                              <1> 	; 28/07/2013
  2251 00004C8E A2[EC680000]        <1> 	mov 	[u.ttyn], al
  2252                              <1> 	; 13/01/2014
  2253 00004C93 FEC0                <1> 	inc	al
  2254 00004C95 A2[C8680000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2255                              <1> rtty_nc: ; 01/02/2014
  2256                              <1> 	; 29/09/2013
  2257                              <1> 	;mov	ecx, 10
  2258                              <1> 	; 11/01/2022
  2259 00004C9A 29C9                <1> 	sub	ecx, ecx
  2260 00004C9C B10A                <1> 	mov	cl, 10
  2261                              <1> rtty_1: 	; 01/02/2014
  2262                              <1> 	;push 	cx ; 29/09/2013
  2263                              <1> 	; 24/12/2021
  2264 00004C9E 51                  <1> 	push	ecx
  2265                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2266 00004C9F B001                <1> 	mov 	al, 1
  2267 00004CA1 E85A0C0000          <1> 	call 	getc
  2268                              <1> 	; 24/12/2021
  2269 00004CA6 59                  <1> 	pop	ecx
  2270                              <1> 	;pop 	cx ; 29/09/2013	
  2271 00004CA7 7516                <1> 	jnz	short rtty_2
  2272                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2273                              <1> 	               ; / of chars. Is this number non-zero?
  2274 00004CA9 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2275                              <1> 	; 05/10/2013
  2276 00004CAB 8A25[EC680000]      <1> 	mov	ah, [u.ttyn]
  2277                              <1> 	; 29/09/2013
  2278 00004CB1 E898FBFFFF          <1> 	call	sleep
  2279                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2280                              <1>                 ;           / (120 chars.)
  2281                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2282 00004CB6 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2283                              <1> 
  2284                              <1> rtty_idle:
  2285                              <1> 	; 29/07/2013
  2286 00004CB8 E804FBFFFF          <1> 	call 	idle
  2287 00004CBD EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2288                              <1> 	;1:
  2289                              <1> 		; tst 2(r5) / is the number of characters zero
  2290                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2291                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2292                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2293                              <1> 		          ; / contains the next char.
  2294                              <1> 		; dec 2(r5) / decrement the character count
  2295                              <1> rtty_2:
  2296 00004CBF 30C0                <1> 	xor 	al, al
  2297 00004CC1 E83A0C0000          <1> 	call 	getc
  2298 00004CC6 E892000000          <1> 	call	passc
  2299                              <1> 		; jsr r0,passc / move the character to core (user)
  2300                              <1> 	;; 17/10/2015 - 16/07/2015
  2301                              <1> 	; 19/06/2014
  2302                              <1> 	;;jnz	short rtty_nc
  2303 00004CCB 58                  <1> 	pop	eax  ; (20/05/2015)
  2304 00004CCC C3                  <1> 	retn 
  2305                              <1> ;ret1:
  2306                              <1> 		; jmp ret / return to caller via 'ret'
  2307                              <1> 
  2308                              <1> rcvt:   ; < receive/read character from tty >
  2309                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2310                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2311                              <1> 	;
  2312                              <1> 	; Retro UNIX 8086 v1 modification !
  2313                              <1> 	; 
  2314                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2315                              <1> 	;		(exactly different than this one)
  2316                              <1> 	;	was in 'u9.s' file.
  2317                              <1> 	;
  2318 00004CCD 2C0A                <1> 	sub 	al, 10
  2319                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2320                              <1> 	; 16/07/2013
  2321                              <1> 	; 21/05/2013
  2322 00004CCF EBBD                <1>         jmp     short rttys
  2323                              <1>       
  2324                              <1> ;rppt: / read paper tape
  2325                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2326                              <1> ;			 / places
  2327                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2328                              <1> ;		       / also enables read bit in prs
  2329                              <1> ;	jsr	r0,passc / place character in users buffer area
  2330                              <1> ;	br	rppt
  2331                              <1> 
  2332                              <1> rmem: ; / transfer characters from memory to a user area of core
  2333                              <1> 	; 17/10/2015
  2334                              <1> 	; 11/06/2015
  2335                              <1> 	; 24/05/2015
  2336                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2337                              <1> 	;
  2338 00004CD1 8B35[A8680000]      <1> 	mov     esi, [u.fofp]
  2339                              <1> rmem_1:
  2340 00004CD7 8B1E                <1>         mov     ebx, [esi]        
  2341                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2342                              <1> 		               ; / to be transferred to user
  2343 00004CD9 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2344                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2345                              <1> 			    ; / char in memory file
  2346 00004CDB 8A03                <1> 	mov	al, [ebx]
  2347                              <1> 		; movb (r1),r1 / get character from memory file, 
  2348                              <1> 		             ; / put it in r1
  2349 00004CDD E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2350                              <1> 			     ;  / the next byte of the users core area
  2351                              <1> 		; br rmem / continue
  2352 00004CE2 75F3                <1> 	jnz	short rmem_1
  2353                              <1> ret_:
  2354 00004CE4 58                  <1> 	pop	eax ; 09/06/2015
  2355 00004CE5 C3                  <1> 	retn
  2356                              <1> 
  2357                              <1> rlpr:
  2358                              <1> ;1:
  2359                              <1> ;rcrd:
  2360 00004CE6 C705[ED680000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2360 00004CEE 0000                <1>
  2361 00004CF0 E91DE6FFFF          <1> 	jmp	error
  2362                              <1> 		;jmp	error / see 'error' routine
  2363                              <1> 
  2364                              <1> dskr:
  2365                              <1> 	; 12/10/2015
  2366                              <1> 	; 21/08/2015
  2367                              <1> 	; 25/07/2015
  2368                              <1> 	; 10/07/2015
  2369                              <1> 	; 16/06/2015
  2370                              <1> 	; 31/05/2015
  2371                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2372                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2373                              <1> dskr_0:
  2374 00004CF5 50                  <1> 	push	eax
  2375                              <1> 		; mov (sp),r1 / i-number in r1
  2376                              <1> 	; AX = i-number
  2377 00004CF6 E834FDFFFF          <1> 	call	iget
  2378                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2379 00004CFB 0FB715[98650000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2380                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2381 00004D02 8B1D[A8680000]      <1> 	mov	ebx, [u.fofp]
  2382 00004D08 2B13                <1> 	sub	edx, [ebx]
  2383                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2384                              <1>         ; 12/10/2015
  2385                              <1> 	; jna     short ret_ 
  2386                              <1> 		; blos ret
  2387 00004D0A 7709                <1> 	ja	short dskr_1
  2388                              <1> 	;
  2389                              <1> dskr_retn: ; 12/10/2015
  2390 00004D0C 58                  <1> 	pop	eax
  2391 00004D0D C605[FF680000]00    <1> 	mov	byte [u.kcall], 0
  2392 00004D14 C3                  <1> 	retn	
  2393                              <1> dskr_1: 
  2394 00004D15 3B15[BC680000]      <1> 	cmp     edx, [u.count] 
  2395                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2396                              <1> 			       ; / to carry out read
  2397 00004D1B 7306                <1> 	jnb	short dskr_2
  2398                              <1> 		; bhis 1f
  2399 00004D1D 8915[BC680000]      <1> 	mov	[u.count], edx
  2400                              <1> 		; mov r2,u.count / no, just read to end of file
  2401                              <1> dskr_2: ; 1:
  2402                              <1> 	; AX = i-number
  2403 00004D23 E89EFBFFFF          <1> 	call	mget
  2404                              <1> 		; jsr r0,mget / returns physical block number of block 
  2405                              <1> 			    ; / in file where offset points
  2406                              <1> 	; eAX = physical block number
  2407 00004D28 E8D3080000          <1> 	call	dskrd
  2408                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2409                              <1> 			     ; / 1st word of data in buffer
  2410                              <1> 	; 09/06/2015
  2411 00004D2D 803D[FF680000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2412 00004D34 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2413 00004D36 66833D[FD680000]00  <1> 	cmp	word [u.pcount], 0
  2414 00004D3E 7705                <1> 	ja	short dskr_4
  2415                              <1> dskr_3:
  2416                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2417 00004D40 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2418                              <1> dskr_4:
  2419                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2420 00004D45 E831030000          <1> 	call	sioreg
  2421                              <1> 		; jsr r0,sioreg
  2422 00004D4A 87F7                <1> 	xchg	esi, edi
  2423                              <1> 	; eDI = file (user data) offset
  2424                              <1> 	; eSI = sector (I/O) buffer offset
  2425                              <1> 	; eCX = byte count
  2426 00004D4C F3A4                <1> 	rep	movsb
  2427                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2428                              <1> 		                 ; / starting at u.base
  2429                              <1> 		; dec r3
  2430                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2431                              <1> 	; 25/07/2015
  2432                              <1> 	; eax = remain bytes in buffer
  2433                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2434 00004D4E 09C0                <1> 	or	eax, eax
  2435 00004D50 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2436                              <1> 	; 03/08/2013
  2437                              <1> 	;pop	eax
  2438 00004D52 390D[BC680000]      <1> 	cmp	[u.count], ecx ; 0
  2439                              <1> 		; tst u.count / all bytes read off disk
  2440                              <1> 		; bne dskr
  2441                              <1> 		; br ret
  2442                              <1>         ;ja	short dskr_0
  2443                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2444                              <1> 	;retn
  2445                              <1> 	; 12/10/2015
  2446 00004D58 76B2                <1> 	jna	short dskr_retn
  2447 00004D5A 58                  <1> 	pop	eax  ; (i-node number)
  2448 00004D5B EB98                <1> 	jmp	short dskr_0
  2449                              <1> 	
  2450                              <1> passc:
  2451                              <1> 	; 18/10/2015
  2452                              <1> 	; 10/07/2015
  2453                              <1> 	; 01/07/2015
  2454                              <1> 	; 08/06/2015
  2455                              <1> 	; 04/06/2015
  2456                              <1> 	; 20/05/2015
  2457                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2458                              <1> 	;
  2459                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2460                              <1> 	;		      to physical address
  2461 00004D5D 66833D[FD680000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2462                              <1> 			     ; 1-4095 --> use previous physical base address
  2463                              <1> 			     ; in [u.pbase]
  2464 00004D65 7705                <1> 	ja	short passc_3
  2465                              <1> 	; 08/06/2015 - 10/07/2015
  2466 00004D67 E82C000000          <1> 	call	trans_addr_w
  2467                              <1> passc_3:
  2468                              <1> 	; 19/05/2015
  2469 00004D6C 66FF0D[FD680000]    <1> 	dec	word [u.pcount]
  2470                              <1> 	;
  2471 00004D73 8B1D[F9680000]      <1> 	mov	ebx, [u.pbase]
  2472 00004D79 8803                <1> 	mov	[ebx], al
  2473                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2474                              <1> 		               ; / users buffer
  2475 00004D7B FF05[B8680000]      <1> 	inc	dword [u.base]
  2476                              <1> 		; inc u.base / increment the pointer to point to 
  2477                              <1> 			  ; / the next byte in users buffer
  2478 00004D81 FF05[F9680000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2479 00004D87 FF05[C0680000]      <1> 	inc	dword [u.nread]
  2480                              <1> 		; inc u.nread / increment the number of bytes read
  2481 00004D8D FF0D[BC680000]      <1> 	dec	dword [u.count]
  2482                              <1> 		; dec u.count / decrement the number of bytes to be read
  2483                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2484 00004D93 C3                  <1> 	retn
  2485                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2486                              <1> 		             ; / 'readi' by:
  2487                              <1> 		;/ (1) pop the return address off the stack into r0
  2488                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2489                              <1> 	;1:
  2490                              <1> 		; clr	*$ps / clear processor status
  2491                              <1> 		; rts r0 / return to address currently on top of stack
  2492                              <1> 
  2493                              <1> trans_addr_r:
  2494                              <1> 	; Translate virtual address to physical address 
  2495                              <1> 	; for reading from user's memory space
  2496                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2497                              <1> 	; 18/10/2015
  2498                              <1> 	; 10/07/2015
  2499                              <1> 	; 09/06/2015
  2500                              <1> 	; 08/06/2015 
  2501                              <1> 	; 04/06/2015
  2502                              <1> 	;
  2503                              <1> 	; 18/10/2015
  2504 00004D94 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2505 00004D96 EB04                <1> 	jmp 	short trans_addr_rw
  2506                              <1> 
  2507                              <1> 	;push	eax
  2508                              <1> 	;push	ebx
  2509                              <1> 	;mov	ebx, [u.base]
  2510                              <1> 	;call	get_physical_addr ; get physical address
  2511                              <1> 	;;jnc	short cpass_0
  2512                              <1> 	;jnc	short passc_1
  2513                              <1> 	;mov	[u.error], eax
  2514                              <1> 	;;pop	ebx
  2515                              <1> 	;;pop	eax
  2516                              <1> 	;jmp	error
  2517                              <1> ;cpass_0:
  2518                              <1> 	; 18/10/2015
  2519                              <1> 	; 20/05/2015
  2520                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2521                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2522                              <1> 	;pop	ebx
  2523                              <1> 	;pop	eax
  2524                              <1> 	;retn	; 08/06/2015
  2525                              <1> 
  2526                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2527                              <1> trans_addr_w:
  2528                              <1> 	; 31/12/2021
  2529                              <1> 	; Translate virtual address to physical address 
  2530                              <1> 	; for writing to user's memory space
  2531                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2532                              <1> 	; 18/10/2015
  2533                              <1> 	; 29/07/2015
  2534                              <1> 	; 10/07/2015
  2535                              <1> 	; 09/06/2015
  2536                              <1> 	; 08/06/2015
  2537                              <1> 	; 04/06/2015 (passc)
  2538                              <1> 	;
  2539                              <1> 	; 18/10/2015
  2540 00004D98 29D2                <1> 	sub	edx, edx
  2541 00004D9A FEC2                <1> 	inc	dl ; 1 (write access sign)
  2542                              <1> trans_addr_rw:
  2543 00004D9C 50                  <1> 	push	eax
  2544 00004D9D 53                  <1> 	push	ebx
  2545                              <1> 	; 18/10/2015
  2546 00004D9E 52                  <1> 	push 	edx ; r/w sign (in DL)
  2547                              <1> 	;
  2548 00004D9F 8B1D[B8680000]      <1> 	mov	ebx, [u.base]
  2549 00004DA5 E843DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2550 00004DAA 730A                <1> 	jnc	short passc_0
  2551 00004DAC A3[ED680000]        <1> 	mov	[u.error], eax
  2552                              <1> 	;pop	edx
  2553                              <1> 	;pop 	ebx
  2554                              <1> 	;pop	eax
  2555 00004DB1 E95CE5FFFF          <1> 	jmp	error
  2556                              <1> passc_0:
  2557 00004DB6 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2558 00004DB9 5A                  <1> 	pop	edx ; 18/10/2015
  2559 00004DBA 7517                <1> 	jnz	short passc_1
  2560                              <1> 	; 18/10/2015
  2561 00004DBC 20D2                <1> 	and 	dl, dl
  2562 00004DBE 7413                <1> 	jz	short passc_1
  2563                              <1> 	; 20/05/2015
  2564                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2565                              <1> 	; EBX = linear address
  2566 00004DC0 51                  <1> 	push 	ecx
  2567 00004DC1 53                  <1> 	push	ebx ; * ; 31/12/2021 (BugFix)
  2568 00004DC2 E895DBFFFF          <1> 	call 	copy_page
  2569 00004DC7 5B                  <1> 	pop	ebx ; * ; 31/12/2021 (BugFix)
  2570 00004DC8 59                  <1> 	pop	ecx
  2571 00004DC9 7217                <1> 	jc	short passc_2
  2572                              <1> 	; 24/12/2021
  2573                              <1> 	;push	eax ; physical address of the new/allocated page
  2574                              <1> 	;call	add_to_swap_queue
  2575                              <1> 	;pop	eax
  2576                              <1> 	; 18/10/2015
  2577 00004DCB 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2578                              <1> 	;mov 	ecx, PAGE_SIZE
  2579                              <1> 	;sub	ecx, ebx 
  2580 00004DD1 01D8                <1> 	add	eax, ebx  
  2581                              <1> passc_1: 
  2582                              <1> 	; 18/10/2015
  2583                              <1> 	; 20/05/2015
  2584 00004DD3 A3[F9680000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2585 00004DD8 66890D[FD680000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2586 00004DDF 5B                  <1> 	pop	ebx
  2587 00004DE0 58                  <1> 	pop	eax
  2588 00004DE1 C3                  <1> 	retn	; 08/06/2015
  2589                              <1> passc_2:
  2590 00004DE2 C705[ED680000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2590 00004DEA 0000                <1>
  2591                              <1> 	;pop 	ebx
  2592                              <1> 	;pop	eax
  2593 00004DEC E921E5FFFF          <1> 	jmp	error
  2594                              <1> 
  2595                              <1> writei:
  2596                              <1> 	; 13/06/2022
  2597                              <1> 	; 03/02/2022
  2598                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2599                              <1> 	; 20/05/2015
  2600                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2601                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2602                              <1> 	;
  2603                              <1> 	; Write data to file with inode number in R1
  2604                              <1> 	; 
  2605                              <1> 	; INPUTS ->
  2606                              <1> 	;    r1 - inode number
  2607                              <1> 	;    u.count - byte count to be written
  2608                              <1> 	;    u.base - points to user buffer
  2609                              <1> 	;    u.fofp - points to word with current file offset
  2610                              <1> 	; OUTPUTS ->
  2611                              <1> 	;    u.count - cleared
  2612                              <1> 	;    u.nread - accumulates total bytes passed back	
  2613                              <1> 	; ((AX = R1))
  2614                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2615                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2616                              <1> 
  2617 00004DF1 31C9                <1> 	xor	ecx, ecx
  2618 00004DF3 890D[C0680000]      <1> 	mov 	[u.nread], ecx  ; 0
  2619                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2620                              <1> 		            ; / read or write calls
  2621 00004DF9 66890D[FD680000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2622 00004E00 390D[BC680000]      <1> 	cmp 	[u.count], ecx
  2623                              <1> 	;	; tst u.count / test the byte count specified by the user
  2624 00004E06 770B                <1> 	ja 	short writei_1 ; 1f
  2625                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2626                              <1> 
  2627                              <1> 	; 13/06/2022 - ('get/read LPT printer status' modification)
  2628 00004E08 83F810              <1> 	cmp	eax, 16  ; LPR_INODE ; lpt (parallel port printer) ?
  2629 00004E0B 7505                <1> 	jne	short writei_0
  2630 00004E0D E924010000          <1> 	jmp	lpr_stat	; get/read line status
  2631                              <1> writei_0:
  2632 00004E12 C3                  <1> 	retn
  2633                              <1> 	;	; rts r0 / no, return - no writing to do
  2634                              <1> writei_1: ;1:
  2635                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2636 00004E13 6683F828            <1> 	cmp 	ax, 40
  2637                              <1> 		; cmp r1,$40.
  2638                              <1> 		; / does the i-node number indicate a special file?
  2639                              <1> 	;ja	dskw 
  2640                              <1> 		; bgt dskw / no, branch to standard file output
  2641                              <1> 	; 24/12/2021
  2642 00004E17 7605                <1> 	jna	short writei_3
  2643 00004E19 E958010000          <1> 	jmp	dskw
  2644                              <1> writei_3:
  2645                              <1> 	; (20/05/2015)
  2646 00004E1E 50                  <1> 	push	eax ; because subroutines will jump to 'wret'
  2647 00004E1F 0FB6D8              <1> 	movzx	ebx, al
  2648                              <1> 	; 03/02/2022
  2649 00004E22 C1E302              <1> 	shl	ebx, 2
  2650                              <1> 	;shl	bx, 2
  2651                              <1> 		; asl r1 / yes, calculate the index into the special file
  2652 00004E25 81C3[294E0000]      <1> 	add	ebx, writei_2 - 4
  2653 00004E2B FF23                <1> 	jmp	dword [ebx]	
  2654                              <1> 		; jmp *1f-2(r1)
  2655                              <1> 		; / jump table and jump to the appropriate routine
  2656                              <1> writei_2: ;1:
  2657 00004E2D [794E0000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2658                              <1> 		 ;wtty / tty; r1=2
  2659                              <1> 		 ;wppt / ppt; r1=4
  2660 00004E31 [CC4E0000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2661                              <1> 		 ;wmem / mem; r1=6
  2662                              <1> 		 ;wrf0 / rf0
  2663                              <1> 		 ;wrk0 / rk0
  2664                              <1> 		 ;wtap / tap0
  2665                              <1> 		 ;wtap / tap1
  2666                              <1> 		 ;wtap / tap2
  2667                              <1> 		 ;wtap / tap3
  2668                              <1> 		 ;wtap / tap4
  2669                              <1> 		 ;wtap / tap5
  2670                              <1> 		 ;wtap / tap6
  2671                              <1> 		 ;wtap / tap7
  2672 00004E35 [3A550000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2673 00004E39 [3A550000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2674 00004E3D [3A550000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2675 00004E41 [3A550000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2676 00004E45 [3A550000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2677 00004E49 [3A550000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2678 00004E4D [FC4E0000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2679 00004E51 [C64E0000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2680                              <1> 		 ;xmtt / tty0
  2681 00004E55 [C64E0000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2682                              <1> 		 ;xmtt / tty1
  2683 00004E59 [C64E0000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2684                              <1> 		 ;xmtt / tty2
  2685 00004E5D [C64E0000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2686                              <1> 		 ;xmtt / tty3
  2687 00004E61 [C64E0000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2688                              <1> 		 ;xmtt / tty4
  2689 00004E65 [C64E0000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2690                              <1> 		 ;xmtt / tty5
  2691 00004E69 [C64E0000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2692                              <1> 		 ;xmtt / tty6
  2693 00004E6D [C64E0000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2694                              <1> 		 ;xmtt / tty7
  2695 00004E71 [C64E0000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2696                              <1> 		; / wlpr / lpr
  2697 00004E75 [C64E0000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2698                              <1> 
  2699                              <1> wtty: ; write to console tty (write to screen)
  2700                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2701                              <1> 	; 18/11/2015
  2702                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2703                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2704                              <1> 	;
  2705                              <1> 	; Console tty output is on current video page
  2706                              <1> 	; Console tty character output procedure is changed here
  2707                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2708                              <1> 	;
  2709 00004E79 0FB61D[E7680000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2710 00004E80 8AA3[F3650000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2711 00004E86 88E0                <1> 	mov	al, ah ; 07/07/2014
  2712                              <1> wttys:	
  2713                              <1> 	; 10/10/2013
  2714 00004E88 8825[EC680000]      <1> 	mov 	[u.ttyn], ah
  2715                              <1> 	; 13/01/2014
  2716 00004E8E FEC0                <1> 	inc	al
  2717 00004E90 A2[C9680000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2718                              <1> wtty_nc: ; 15/05/2013
  2719                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2720 00004E95 E881010000          <1> 	call	cpass
  2721                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2722                              <1> 		             ; / none go to return address in syswrite
  2723                              <1> 		; tst r1 / is character = null
  2724                              <1> 		; beq wtty / yes, get next character
  2725                              <1> 	; 10/10/2013
  2726 00004E9A 7428                <1> 	jz	short wret
  2727                              <1> 	;1 : 
  2728                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2729                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2730                              <1> 		;	          / than 20
  2731                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2732                              <1> 	; 27/06/2014
  2733                              <1> wtty_1:
  2734                              <1> 	; AH = tty number
  2735                              <1> 	; AL = ASCII code of the character
  2736                              <1> 	; 15/04/2014
  2737                              <1> 	;push	ax
  2738                              <1> 	; 24/12/2021
  2739 00004E9C 50                  <1> 	push	eax
  2740 00004E9D E8CC0A0000          <1> 	call	putc ; 14/05/2013
  2741 00004EA2 731D                <1> 	jnc	short wtty_2
  2742                              <1> 	; 18/11/2015
  2743 00004EA4 E818F9FFFF          <1> 	call	idle
  2744                              <1> 	;mov	ax, [esp]
  2745                              <1> 	; 24/12/2021
  2746 00004EA9 8B0424              <1> 	mov	eax, [esp]
  2747 00004EAC E8BD0A0000          <1> 	call	putc
  2748 00004EB1 730E                <1> 	jnc	short wtty_2 
  2749                              <1> 	; 02/06/2014
  2750 00004EB3 8A25[EC680000]      <1> 	mov	ah, [u.ttyn]
  2751 00004EB9 E890F9FFFF          <1> 	call	sleep
  2752                              <1> 	;pop	ax
  2753                              <1> 	; 24/12/2021
  2754 00004EBE 58                  <1> 	pop	eax
  2755 00004EBF EBDB                <1> 	jmp 	short wtty_1
  2756                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2757                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2758                              <1> 			      ; / console tty and
  2759                              <1> 		; br 	2f / place character in list; if none available
  2760                              <1> 		   	  ; / branch to put process to sleep
  2761                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2762                              <1> wtty_2:
  2763                              <1> 	; 15/04/2014
  2764                              <1> 	;pop	ax
  2765                              <1> 	; 24/12/2021
  2766 00004EC1 58                  <1> 	pop	eax
  2767 00004EC2 EBD1                <1> 	jmp	short wtty_nc
  2768                              <1> 		; br wtty
  2769                              <1> wret:	; 10/10/2013 (20/05/2015)
  2770 00004EC4 58                  <1> 	pop	eax
  2771 00004EC5 C3                  <1> 	retn
  2772                              <1> 	;2:
  2773                              <1> 		;mov	r1,-(sp) / place character on stack
  2774                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2775                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2776                              <1> 		;br	1b / try again to place character in clist and output
  2777                              <1> 
  2778                              <1> xmtt:   ; < send/write character to tty >
  2779                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2780                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2781                              <1> 	;
  2782                              <1> 	; Retro UNIX 8086 v1 modification !
  2783                              <1> 	; 
  2784                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2785                              <1> 	;		(exactly different than this one)
  2786                              <1> 	;	was in 'u9.s' file.
  2787                              <1> 	;
  2788 00004EC6 2C0A                <1> 	sub 	al, 10
  2789                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2790                              <1> 	; 10/10/2013
  2791 00004EC8 88C4                <1> 	mov	ah, al
  2792                              <1> 	; 28/07/2013
  2793 00004ECA EBBC                <1> 	jmp	short wttys
  2794                              <1> 
  2795                              <1> ;wppt:
  2796                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2797                              <1> ;		         / if none return to writei's calling routine
  2798                              <1> ;	jsr	r0,pptoc / output character on ppt
  2799                              <1> ;	br	wppt
  2800                              <1> 
  2801                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2802                              <1> 	; 17/10/2015
  2803                              <1> 	; 11/06/2015
  2804                              <1> 	; 24/05/2015
  2805                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2806                              <1> 	;
  2807 00004ECC 813D[10070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2807 00004ED2 [E4470000]          <1>
  2808 00004ED6 7415                <1>         je      short wmem_acc_err
  2809                              <1> 	;
  2810 00004ED8 8B35[A8680000]      <1>         mov     esi, [u.fofp] 
  2811                              <1> wmem_1:
  2812 00004EDE E838010000          <1> 	call	cpass
  2813                              <1> 		; jsr r0,cpass / get next character from users area of
  2814                              <1> 			     ; / core and put it in r1
  2815                              <1>         	; mov r1,-(sp) / put character on the stack
  2816                              <1> 	; 20/09/2013
  2817 00004EE3 74DF                <1> 	jz	short wret ; wmem_2  
  2818 00004EE5 8B1E                <1>         mov     ebx, [esi]
  2819                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2820 00004EE7 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2821                              <1> 		; inc *u.fofp / increment file offset to point to next
  2822                              <1> 			    ; / available location in file
  2823 00004EE9 8803                <1> 	mov	[ebx], al	
  2824                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2825                              <1> 			        ; / assigned to it
  2826 00004EEB EBF1                <1> 	jmp	short wmem_1
  2827                              <1> 		; br wmem / continue
  2828                              <1> 	;1:
  2829                              <1> 	;jmp	error / ?
  2830                              <1> ;wmem_2:	
  2831                              <1> ;	; 20/09/2013
  2832                              <1> ;	pop	ax
  2833                              <1> ;	retn
  2834                              <1> 
  2835                              <1> wmem_acc_err:
  2836 00004EED C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2836 00004EF5 0000                <1>
  2837 00004EF7 E916E4FFFF          <1> 	jmp	error
  2838                              <1> 
  2839                              <1> ;wlpr:
  2840                              <1> 	; 13/06/2022
  2841                              <1> 	;mov	dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2842                              <1> 	;jmp	error   ; ... Printing procedure will be located here ...
  2843                              <1> 		;/	jsr	r0,cpass
  2844                              <1> 		;/	cmp	r0,$'a
  2845                              <1> 		;/	blo	1f
  2846                              <1> 		;/	cmp	r1,$'z
  2847                              <1> 		;/	bhi	1f
  2848                              <1> 		;/	sub	$40,r1
  2849                              <1> 		;/1:
  2850                              <1> 		;/	jsr	r0,lptoc
  2851                              <1> 		;/	br	wlpr
  2852                              <1> 		; br rmem / continue
  2853                              <1> 
  2854                              <1> ; 13/06/2022 - Retro UNIX 386 v1.1 - PRINTER BIOS (Functions)
  2855                              <1> 
  2856                              <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM)
  2857                              <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987
  2858                              <1> ;; 23/03/2018 - Retro DOS v2.0
  2859                              <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2)
  2860                              <1> 
  2861                              <1> ; IBM ROMBIOS (INT 17h) STATUS BITS
  2862                              <1> 
  2863                              <1> NOTBUSYSTATUS	equ 10000000b	; NOT BUSY
  2864                              <1> ACKSTATUS	equ 01000000b	; ACKNOWLEDGE (FOR WHAT?)
  2865                              <1> NOPAPERSTATUS	equ 00100000b	; NO MORE PAPER
  2866                              <1> SELECTEDSTATUS	equ 00010000b	; THE PRINTER SAID IT WAS SELECTED
  2867                              <1> IOERRSTATUS	equ 00001000b	; SOME KIND ERROR
  2868                              <1> RESERVED	equ 00000110b	; NOPS
  2869                              <1> TIMEOUTSTATUS	equ 00000001b	; TIME OUT.
  2870                              <1> 
  2871                              <1> ;----------------------------------------------------------------
  2872                              <1> ;								:
  2873                              <1> ;		WRITE TO PRINTER DEVICE 			:
  2874                              <1> ;								:
  2875                              <1> ;   CX has count of bytes to be printed 			:
  2876                              <1> ;   ES:DI point to source buffer contains characters		:
  2877                              <1> ;   AuxNum (in msbio.asm) has printer number			:
  2878                              <1> ;								:
  2879                              <1> ;----------------------------------------------------------------
  2880                              <1> 
  2881                              <1> wlpr:
  2882                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2883                              <1> PRN$WRIT:
  2884                              <1> 	; INPUT:
  2885                              <1> 	;	[u.count] = count of characters to be printed
  2886                              <1> 	;	[u.base] = buffer address in user's memory space
  2887                              <1> 	;
  2888                              <1> 	;	(if ECX = 0, printer status will be returned)
  2889                              <1> 	
  2890                              <1> 	;xor	ebx, ebx
  2891                              <1> PRN$LOOP:
  2892 00004EFC E81A010000          <1> 	call	cpass		  ; Get a character into AL
  2893 00004F01 7431                <1> 	jz	short pr_exit
  2894                              <1> 	;
  2895 00004F03 B302                <1> 	mov	bl, 2  ; retry count
  2896                              <1> PRN$OUT:
  2897                              <1> 	; al = character which will be printed
  2898 00004F05 30E4                <1> 	xor	ah, ah ; 0	  ; PRINT THE CHARACTER IN (AL)
  2899 00004F07 E850000000          <1> 	call	PRNOP
  2900 00004F0C 74EE                <1> 	jz	short PRN$LOOP 	  ; if error, try to print again
  2901                              <1> PrRetry:
  2902                              <1> 	; al = character
  2903 00004F0E FECB                <1> 	dec	bl
  2904 00004F10 75F3                <1> 	jnz	short PRN$OUT
  2905                              <1> pr_err_exit:
  2906 00004F12 0FB6C0              <1> 	movzx	eax, al
  2907 00004F15 A3[ED680000]        <1> 	mov	[u.error], eax
  2908 00004F1A A3[98680000]        <1> 	mov	[u.r0], eax ; error code in AL
  2909 00004F1F 8B2D[90680000]      <1> 	mov 	ebp, [u.sp]
  2910                              <1> 			; Kernel stack at the beginning of sys call
  2911 00004F25 8B15[C0680000]      <1> 	mov	edx, [u.nread]
  2912 00004F2B 4A                  <1> 	dec	edx ; last char failed
  2913 00004F2C 895514              <1> 	mov	[ebp+20], edx ; count of printed chacters in edx
  2914 00004F2F E9DEE3FFFF          <1> 	jmp	error
  2915                              <1> pr_exit:
  2916 00004F34 58                  <1> 	pop	eax ; inode number
  2917                              <1> 
  2918                              <1> 	;mov	eax, [u.nread]
  2919                              <1> 	;mov	[u.r0], eax ; count of printed chacters
  2920                              <1> 	;jmp	sysret
  2921 00004F35 C3                  <1> 	retn	; return from writei to syswrite (rw0)
  2922                              <1> 
  2923                              <1> ; 13/06/2022
  2924                              <1> 
  2925                              <1> ;----------------------------------------------------------------
  2926                              <1> ;								:
  2927                              <1> ;		PRINTER STATUS ROUTINE				:
  2928                              <1> ;								:
  2929                              <1> ;----------------------------------------------------------------
  2930                              <1> ;
  2931                              <1> 
  2932                              <1> lpr_stat:
  2933                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2934                              <1> PRN$STAT:
  2935 00004F36 E81F000000          <1> 	call	PRNSTAT		  ; get the status
  2936 00004F3B 750E                <1> 	jnz	short prn_stat_retn
  2937                              <1> 				  ; if error jump to error routine
  2938                              <1> 	;mov	al, 9		  ; AGAIN, ASSUME OUT OF PAPER...
  2939 00004F3D B01F                <1> 	mov	al, ERR_PRN_PAPER
  2940 00004F3F F6C420              <1> 	test	ah, NOPAPERSTATUS
  2941 00004F42 7507                <1> 	jnz	short prn_stat_retn
  2942 00004F44 F6C480              <1> 	test	ah, NOTBUSYSTATUS
  2943 00004F47 750D                <1> 	jnz	short prn_stat_ok ; if not busy return (with cf=0)
  2944 00004F49 B022                <1> 	mov	al, ERR_PRN_BUSY  ; else busy, return to busy exit
  2945                              <1> prn_stat_retn:
  2946                              <1> 	; al = error code
  2947                              <1> 	; ah = status flags
  2948 00004F4B A3[98680000]        <1> 	mov	[u.r0], eax
  2949                              <1> 	;movzx	eax, al
  2950                              <1> 	;mov 	[u.error], eax
  2951 00004F50 58                  <1> 	pop	eax ; discard return address to syswrite
  2952 00004F51 E9DCE3FFFF          <1> 	jmp	sysret
  2953                              <1> prn_stat_ok:
  2954 00004F56 30C0                <1> 	xor	al, al ; 0
  2955 00004F58 EBF1                <1> 	jmp	short prn_stat_retn
  2956                              <1> 
  2957                              <1> ;
  2958                              <1> ;   PRNSTAT	get printer status
  2959                              <1> ;   PRNOP	print a character
  2960                              <1> ;
  2961                              <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS
  2962                              <1> ; printer routines.  The routines share code which calls on the bios and
  2963                              <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ
  2964                              <1> ; only by the value put into AH before the ROM-BIOS call.
  2965                              <1> ;
  2966                              <1> ;   INPUT	if PRNOP then character in AL
  2967                              <1> ;
  2968                              <1> ;   OUTPUT	- AL holds error code
  2969                              <1> ;		- AH status byte from printer
  2970                              <1> ;		- flag NZ if error
  2971                              <1> 
  2972                              <1> PRNSTAT:
  2973 00004F5A B402                <1> 	mov	ah, 2		  ; set command for get status 
  2974                              <1> 
  2975                              <1> PRNOP:
  2976                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2977                              <1> 	;
  2978                              <1> 	; Print character (on paper)
  2979                              <1> 
  2980                              <1> 	; INPUT:
  2981                              <1> 	;	al = character to be printed
  2982                              <1> 	; OUTPUT:
  2983                              <1> 	;	zf = 1 -> ok
  2984                              <1> 	;	zf = 0 -> error code in AL
  2985                              <1> 
  2986 00004F5C E8460C0000          <1> 	call	int17h	 ; call lpt bios
  2987                              <1> 	
  2988 00004F61 F6C408              <1> 	test	ah, IOERRSTATUS	  ; I/O ERROR?
  2989 00004F64 740A                <1> 	jz	short short prnop_chk_nrdy ; NO, TRY NOT READY
  2990                              <1> 
  2991                              <1> 	; AT THIS POINT, WE KNOW WE HAVE AN ERROR.
  2992                              <1> 	; THE CONVERSE IS NOT TRUE.
  2993                              <1> 
  2994                              <1> 	;mov	al, 9		  ; FIRST, ASSUME OUT OF PAPER
  2995 00004F66 B01F                <1> 	mov	al, ERR_PRN_PAPER
  2996 00004F68 F6C420              <1> 	test	ah, NOPAPERSTATUS ; OUT OF PAPER SET?
  2997 00004F6B 7502                <1> 	jnz	short PRNOP1	  ; YES, ERROR IS SET
  2998                              <1> 	;mov	al, ERR_PRN_IO
  2999 00004F6D FEC0                <1> 	inc	al		  ; INDICATE I/O ERROR
  3000                              <1> PRNOP1: 
  3001                              <1> 
  3002                              <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)
  3003                              <1> 
  3004 00004F6F C3                  <1> 	retn			  ; RETURN WITH ERROR
  3005                              <1>  
  3006                              <1> ; THE BITS SAID NO ERROR.
  3007                              <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE.
  3008                              <1> 
  3009                              <1> prnop_chk_nrdy:
  3010                              <1> 	;mov	al, 2		  ; ASSUME NOT-READY
  3011 00004F70 B019                <1> 	mov	al, ERR_PRN_TIMEOUT ; ''time out !' error
  3012                              <1> 	
  3013 00004F72 F6C401              <1> 	test	ah, TIMEOUTSTATUS ; IS TIME-OUT SET?
  3014                              <1> 				  ; IF NZ THEN ERROR, ELSE OK???
  3015                              <1> PRNOP2: 
  3016 00004F75 C3                  <1> 	retn
  3017                              <1> 
  3018                              <1> 
  3019                              <1> dskw: ; / write routine for non-special files
  3020                              <1> 	;
  3021                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3022                              <1> 	; 25/07/2015
  3023                              <1> 	; 16/06/2015
  3024                              <1> 	; 09/06/2015
  3025                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  3026                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  3027                              <1> 	;
  3028                              <1> 	; 01/08/2013 (mkdir_w check)
  3029                              <1> 
  3030                              <1> 	;push	ax ; 26/04/2013
  3031                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  3032                              <1> 	; 24/12/2021
  3033 00004F76 50                  <1> 	push	eax
  3034                              <1> 	; AX = inode number
  3035 00004F77 E8B3FAFFFF          <1> 	call	iget
  3036                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  3037                              <1> 		            ; / read i-node 'r1' into i-node area of core
  3038 00004F7C 8B1D[A8680000]      <1>         mov     ebx, [u.fofp] 
  3039 00004F82 8B13                <1> 	mov 	edx, [ebx]
  3040                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  3041                              <1> 			       ; / in the fsp entry for this file] in r2
  3042 00004F84 0315[BC680000]      <1> 	add 	edx, [u.count]	
  3043                              <1> 		; add u.count,r2 / no. of bytes to be written
  3044                              <1> 			       ; / + file offset is put in r2
  3045                              <1> 	; 16/06/2015        
  3046 00004F8A 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  3047 00004F90 760F                <1> 	jna	short dskw_0
  3048 00004F92 C705[ED680000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  3048 00004F9A 0000                <1>
  3049 00004F9C E971E3FFFF          <1> 	jmp	error
  3050                              <1> dskw_0:	
  3051 00004FA1 663B15[98650000]    <1> 	cmp     dx, [i.size]
  3052                              <1> 		; cmp r2,i.size / is this greater than the present size of
  3053                              <1> 		              ; / the file?
  3054 00004FA8 760C                <1> 	jna	short dskw_1
  3055                              <1> 		; blos 1f / no, branch
  3056 00004FAA 668915[98650000]    <1>         mov     [i.size], dx
  3057                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  3058                              <1> 			      ; / file offset + no. of data bytes
  3059 00004FB1 E883FBFFFF          <1> 	call	setimod
  3060                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  3061                              <1> 		          ; / modified), stuff time of modification into
  3062                              <1> 	          	  ; / core image of i-node
  3063                              <1> dskw_1: ; 1:	
  3064 00004FB6 E80BF9FFFF          <1> 	call	mget
  3065                              <1> 	; eAX = Block number
  3066                              <1> 		; jsr r0,mget / get the block no. in which to write 
  3067                              <1> 			    ; /	the next data byte
  3068                              <1> 	; eax = block number
  3069 00004FBB 8B1D[A8680000]      <1> 	mov     ebx, [u.fofp]
  3070 00004FC1 8B13                <1> 	mov	edx, [ebx]
  3071 00004FC3 81E2FF010000        <1> 	and	edx, 1FFh  
  3072                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  3073 00004FC9 750C                <1> 	jnz	short dskw_2
  3074                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  3075                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  3076 00004FCB 813D[BC680000]0002- <1> 	cmp	dword [u.count], 512
  3076 00004FD3 0000                <1>
  3077                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  3078                              <1> 				  ; / an entire block? (i.e., no. of
  3079 00004FD5 7305                <1> 	jnb	short dskw_3
  3080                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  3081                              <1> 			; / Yes, branch. Don't have to read block
  3082                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  3083                              <1>    		; / overwritten).
  3084 00004FD7 E824060000          <1> 	call	dskrd
  3085                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  3086                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  3087                              <1> dskw_3: ; 3:
  3088                              <1> 	; eAX (r1) = block/sector number
  3089 00004FDC E891060000          <1> 	call	wslot
  3090                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  3091                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  3092 00004FE1 803D[FF680000]00    <1> 	cmp	byte [u.kcall], 0
  3093 00004FE8 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  3094                              <1> 	;
  3095 00004FEA 66833D[FD680000]00  <1> 	cmp	word [u.pcount], 0
  3096 00004FF2 7705                <1> 	ja	short dskw_5
  3097                              <1> dskw_4:
  3098                              <1> 	; [u.base] = virtual address to transfer (as source address)
  3099 00004FF4 E89BFDFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  3100                              <1> dskw_5:
  3101                              <1> 	; eBX (r5) = system (I/O) buffer address
  3102 00004FF9 E87D000000          <1> 	call	sioreg
  3103                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3104                              <1> 			     ; / r1 = address of data, r2 points to location
  3105                              <1> 			     ; / in buffer in which to start writing data
  3106                              <1> 	; eSI = file (user data) offset
  3107                              <1> 	; eDI = sector (I/O) buffer offset
  3108                              <1> 	; eCX = byte count
  3109                              <1> 	;
  3110 00004FFE F3A4                <1>   	rep	movsb
  3111                              <1> 		; movb (r1 )+,(r2)+ 
  3112                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3113                              <1> 		; dec r3 / decrement no. of bytes to be written
  3114                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3115                              <1> 	; 25/07/2015
  3116                              <1> 	; eax = remain bytes in buffer
  3117                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3118 00005000 09C0                <1> 	or	eax, eax
  3119 00005002 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  3120                              <1> dskw_6:
  3121 00005004 E885060000          <1> 	call	dskwr
  3122                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3123 00005009 833D[BC680000]00    <1>         cmp     dword [u.count], 0
  3124                              <1> 		; tst u.count / any more data to write?
  3125 00005010 77A4                <1> 	ja	short dskw_1
  3126                              <1> 		; bne 1b / yes, branch
  3127                              <1> 	; 03/08/2013
  3128 00005012 C605[FF680000]00    <1> 	mov	byte [u.kcall], 0
  3129                              <1> 	; 20/09/2013 (;;)
  3130                              <1> 	;pop	ax
  3131                              <1> 	; 24/12/2021
  3132 00005019 58                  <1> 	pop	eax
  3133 0000501A C3                  <1> 	retn
  3134                              <1> 	;;jmp 	short dskw_ret 
  3135                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3136                              <1> 
  3137                              <1> cpass: ; / get next character from user area of core and put it in r1
  3138                              <1> 	; 18/10/2015
  3139                              <1> 	; 10/10/2015
  3140                              <1> 	; 10/07/2015
  3141                              <1> 	; 02/07/2015
  3142                              <1> 	; 01/07/2015
  3143                              <1> 	; 24/06/2015
  3144                              <1> 	; 08/06/2015
  3145                              <1> 	; 04/06/2015
  3146                              <1> 	; 20/05/2015
  3147                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3148                              <1> 	;
  3149                              <1> 	; INPUTS -> 
  3150                              <1> 	;     [u.base] = virtual address in user area
  3151                              <1> 	;     [u.count] = byte count (max.)
  3152                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3153                              <1> 	; OUTPUTS -> 
  3154                              <1> 	;     AL = the character which is pointed by [u.base]
  3155                              <1> 	;     zf = 1 -> transfer count has been completed	
  3156                              <1>         ;
  3157                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  3158                              <1> 	;
  3159                              <1> 	;
  3160 0000501B 833D[BC680000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3161                              <1> 		; tst u.count / have all the characters been transferred
  3162                              <1> 			    ; / (i.e., u.count, # of chars. left
  3163 00005022 763F                <1> 	jna	short cpass_3
  3164                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3165 00005024 FF0D[BC680000]      <1> 	dec	dword [u.count]
  3166                              <1> 		; dec u.count / no, decrement u.count
  3167                              <1>         ; 19/05/2015 
  3168                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3169                              <1> 	;		      to physical address
  3170 0000502A 66833D[FD680000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3171                              <1> 			     ; 1-4095 --> use previous physical base address
  3172                              <1> 			     ; in [u.pbase]
  3173 00005032 770E                <1> 	ja	short cpass_1
  3174                              <1> 	; 02/07/2015
  3175 00005034 833D[F5680000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  3176 0000503B 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  3177                              <1> 	; 08/06/2015 - 10/07/2015
  3178 0000503D E852FDFFFF          <1> 	call	trans_addr_r
  3179                              <1> cpass_1:
  3180                              <1> 	; 02/07/2015
  3181                              <1> 	; 24/06/2015
  3182 00005042 66FF0D[FD680000]    <1> 	dec	word [u.pcount]
  3183                              <1> cpass_2: 
  3184                              <1> 	; 10/10/2015
  3185                              <1> 	; 02/07/2015
  3186 00005049 8B15[F9680000]      <1> 	mov	edx, [u.pbase]
  3187 0000504F 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3188                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3189                              <1> 				; / by u.base and put it in r1
  3190 00005051 FF05[C0680000]      <1> 	inc	dword [u.nread]
  3191                              <1> 		; inc u.nread / increment no. of bytes transferred
  3192 00005057 FF05[B8680000]      <1> 	inc	dword [u.base]
  3193                              <1> 		; inc u.base / increment the buffer address to point to the
  3194                              <1> 			   ; / next byte
  3195 0000505D FF05[F9680000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3196                              <1> cpass_3:
  3197 00005063 C3                  <1> 	retn
  3198                              <1> 		; rts	r0 / next byte
  3199                              <1> 	; 1: 
  3200                              <1> 		; mov (sp)+,r0 
  3201                              <1> 		         ; / put return address of calling routine into r0
  3202                              <1> 		; mov (sp)+,r1 / i-number in r1
  3203                              <1> 		; rts r0 / non-local return
  3204                              <1> cpass_k:
  3205                              <1> 	; 02/07/2015
  3206                              <1> 	; The caller is os kernel 
  3207                              <1> 	; (get sysexec arguments from kernel's memory space)
  3208                              <1> 	;
  3209 00005064 8B1D[B8680000]      <1> 	mov	ebx, [u.base]
  3210 0000506A 66C705[FD680000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3210 00005072 10                  <1>
  3211 00005073 891D[F9680000]      <1> 	mov	[u.pbase], ebx
  3212 00005079 EBCE                <1> 	jmp	short cpass_2
  3213                              <1> 	
  3214                              <1> sioreg: 
  3215                              <1> 	; 25/07/2015
  3216                              <1> 	; 18/07/2015
  3217                              <1> 	; 02/07/2015
  3218                              <1> 	; 17/06/2015
  3219                              <1> 	; 09/06/2015
  3220                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3221                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3222                              <1> 	;
  3223                              <1> 	; INPUTS -> 
  3224                              <1> 	;     eBX = system buffer (data) address (r5)
  3225                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3226                              <1> 	;     [u.base] = virtual address of the user buffer
  3227                              <1> 	;     [u.pbase] = physical address of the user buffer
  3228                              <1> 	;     [u.count] = byte count
  3229                              <1> 	;     [u.pcount] = byte count within page frame 			
  3230                              <1> 	; OUTPUTS -> 
  3231                              <1> 	;     eSI = user data offset (r1)
  3232                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3233                              <1> 	;     eCX = byte count (r3)
  3234                              <1> 	;     EAX = remain bytes after byte count within page frame
  3235                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3236                              <1>         ;
  3237                              <1> 	; ((Modified registers:  EDX))
  3238                              <1>  
  3239 0000507B 8B35[A8680000]      <1>         mov     esi, [u.fofp]
  3240 00005081 8B3E                <1>         mov     edi, [esi]
  3241                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3242 00005083 89F9                <1> 	mov	ecx, edi
  3243                              <1> 		; mov r2,r3 / and also to r3
  3244 00005085 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3245                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3246 0000508B 81E7FF010000        <1> 	and	edi, 1FFh
  3247                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3248 00005091 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3249                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3250                              <1> 			  ; / where data is to be placed
  3251                              <1>                 ; mov u.base,r1 / address of data is in r1
  3252 00005093 F7D9                <1> 	neg	ecx
  3253                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3254                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3255 00005095 3B0D[BC680000]      <1> 	cmp	ecx, [u.count]
  3256                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3257                              <1> 			       ; / to be written to the file
  3258 0000509B 7606                <1> 	jna	short sioreg_0
  3259                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3260                              <1> 			 ; / in the file block as the number to be written
  3261 0000509D 8B0D[BC680000]      <1> 	mov	ecx, [u.count]
  3262                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3263                              <1> 			       ; / bytes as the number to be written
  3264                              <1> sioreg_0:
  3265                              <1> 	; 17/06/2015
  3266 000050A3 803D[FF680000]00    <1> 	cmp	byte [u.kcall], 0 
  3267 000050AA 7613                <1> 	jna	short sioreg_1
  3268                              <1> 	; 25/07/2015
  3269                              <1> 	; the caller is 'mkdir' or 'namei'
  3270 000050AC A1[B8680000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3271 000050B1 A3[F9680000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3272 000050B6 66890D[FD680000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3273 000050BD EB0B                <1> 	jmp	short sioreg_2
  3274                              <1> sioreg_1:
  3275                              <1> 	; 25/07/2015
  3276                              <1> 	; 18/07/2015
  3277                              <1> 	; 09/06/2015 
  3278 000050BF 0FB715[FD680000]    <1> 	movzx	edx, word [u.pcount]
  3279                              <1> 		; ecx and [u.pcount] are always > 0, here
  3280 000050C6 39D1                <1> 	cmp	ecx, edx	
  3281 000050C8 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3282                              <1> sioreg_2: ; 2:
  3283 000050CA 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3284                              <1> sioreg_3:
  3285 000050CC 010D[C0680000]      <1> 	add 	[u.nread], ecx
  3286                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3287                              <1> 			         ; / during write is put into u.nread
  3288 000050D2 290D[BC680000]      <1> 	sub 	[u.count], ecx
  3289                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3290                              <1> 			       ; / must be written or read
  3291 000050D8 010D[B8680000]      <1> 	add 	[u.base], ecx
  3292                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3293                              <1> 			      ; / data bytes
  3294 000050DE 010E                <1>         add 	[esi], ecx 
  3295                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3296                              <1> 			       ; / + old file offset
  3297                              <1> 	; 25/07/2015
  3298 000050E0 8B35[F9680000]      <1> 	mov	esi, [u.pbase]
  3299 000050E6 66290D[FD680000]    <1> 	sub	[u.pcount], cx
  3300 000050ED 010D[F9680000]      <1> 	add	[u.pbase], ecx
  3301 000050F3 C3                  <1>         retn
  3302                              <1> 		; rts r0
  3303                              <1> 		; transfer count > [u.pcount]
  3304                              <1> sioreg_4:
  3305                              <1> 	; 25/07/2015
  3306                              <1> 	; transfer count > [u.pcount] 
  3307                              <1> 	; (ecx > edx)
  3308 000050F4 89C8                <1> 	mov	eax, ecx
  3309 000050F6 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3310 000050F8 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3311 000050FA EBD0                <1> 	jmp	short sioreg_3
  2111                                  %include 'u7.s'        ; 18/04/2015
  2112                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS7.INC
  2113                              <1> ; Last Modification: 13/06/2022
  2114                              <1> ; ----------------------------------------------------------------------------
  2115                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2116                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2117                              <1> ;
  2118                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2119                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2120                              <1> ; <Bell Laboratories (17/3/1972)>
  2121                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2122                              <1> ;
  2123                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2124                              <1> ;
  2125                              <1> ; ****************************************************************************
  2126                              <1> 
  2127                              <1> sysmount: ; / mount file system; args special; name
  2128                              <1> 	; 15/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2129                              <1> 	; 09/02/2022
  2130                              <1> 	; 08/02/2022
  2131                              <1> 	; 07/02/2022
  2132                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2133                              <1> 	; 14/11/2015
  2134                              <1> 	; 24/10/2015
  2135                              <1> 	; 13/10/2015
  2136                              <1> 	; 10/07/2015
  2137                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2138                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2139                              <1> 	;
  2140                              <1> 	; 'sysmount' anounces to the system that a removable 
  2141                              <1> 	; file system has been mounted on a special file.
  2142                              <1> 	; The device number of the special file is obtained via
  2143                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2144                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2145                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2146                              <1> 	; to read file system into core, i.e. the first block on the
  2147                              <1> 	; mountable file system is read in. This block is super block
  2148                              <1> 	; for the file system. This call is super user restricted.	
  2149                              <1> 	;
  2150                              <1> 	; Calling sequence:
  2151                              <1> 	;	sysmount; special; name
  2152                              <1> 	; Arguments:
  2153                              <1> 	;	special - pointer to name of special file (device)
  2154                              <1> 	;	name -  pointer to name of the root directory of the
  2155                              <1> 	;		newly mounted file system. 'name' should 
  2156                              <1> 	;		always be a directory.
  2157                              <1> 	; Inputs: - 
  2158                              <1> 	; Outputs: -
  2159                              <1> 	; ...............................................................
  2160                              <1> 	;				
  2161                              <1> 	; Retro UNIX 8086 v1 modification: 
  2162                              <1> 	;       'sysmount' system call has two arguments; so,
  2163                              <1> 	;	* 1st argument, special is pointed to by BX register
  2164                              <1> 	;	* 2nd argument, name is in CX register
  2165                              <1> 	;
  2166                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2167                              <1> 	;	       already modified for IBM PC compatibility and 
  2168                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2169                              <1> 	
  2170                              <1> 	;call	arg2
  2171                              <1> 		; jsr r0,arg2 / get arguments special and name
  2172 000050FC 891D[B0680000]      <1> 	mov	[u.namep], ebx
  2173                              <1> 	; 09/02/2022
  2174                              <1> 	;push	ecx ; directory name
  2175 00005102 66833D[80680000]00  <1> 	cmp	word [mnti], 0
  2176                              <1> 		; tst mnti / is the i-number of the cross device file
  2177                              <1> 			 ; / zero?
  2178                              <1> 	;;ja	error
  2179                              <1>         	; bne errora / no, error
  2180                              <1> 	;ja	sysmnt_err0
  2181                              <1> 	; 11/01/2022
  2182 0000510A 7605                <1> 	jna	short sysmnt_0
  2183 0000510C E968010000          <1> 	jmp	sysmnt_err0
  2184                              <1> sysmnt_0:
  2185                              <1> 	; 09/02/2022
  2186 00005111 51                  <1> 	push	ecx ; directory name
  2187 00005112 E84A010000          <1> 	call	getspl
  2188                              <1> 		; jsr r0,getspl / get special files device number in r1
  2189                              <1> 	; 09/02/2022
  2190 00005117 8F05[B0680000]      <1> 	pop	dword [u.namep] ; directory name
  2191                              <1> 	; 13/10/2015
  2192                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2193                              <1> 	; 11/01/2022
  2194 0000511D 29DB                <1> 	sub	ebx, ebx
  2195 0000511F 88C3                <1> 	mov	bl, al
  2196 00005121 F683[1A600000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2197 00005128 750F                <1> 	jnz	short sysmnt_1
  2198                              <1> sysmnt_err1:
  2199 0000512A C705[ED680000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2199 00005132 0000                <1>
  2200 00005134 E9D9E1FFFF          <1> 	jmp	error
  2201                              <1> sysmnt_1:
  2202                              <1> 	; 09/02/2022
  2203                              <1> 	;pop	dword [u.namep]
  2204                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2205                              <1> 				  ; / on the device
  2206                              <1> 	; 14/11/2015
  2207 00005139 53                  <1> 	push	ebx ; 13/10/2015
  2208                              <1> 		; mov r1,-(sp) / save the device number
  2209                              <1>         ;
  2210 0000513A E8E0F0FFFF          <1> 	call	namei
  2211                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2212                              <1> 		       ; ax = 0 -> file not found 	
  2213                              <1> 	;jz	error
  2214                              <1> 	;jc	error
  2215                              <1> 		; jsr r0,namei / get the i-number of the file
  2216                              <1>                	; br errora
  2217 0000513F 730F                <1> 	jnc	short sysmnt_2
  2218                              <1> sysmnt_err2:
  2219 00005141 C705[ED680000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2219 00005149 0000                <1>
  2220 0000514B E9C2E1FFFF          <1> 	jmp	error
  2221                              <1> sysmnt_2:	
  2222 00005150 66A3[80680000]      <1> 	mov	[mnti], ax
  2223                              <1>         	; mov r1,mnti / put it in mnti
  2224                              <1> 
  2225                              <1> 	; 15/05/2022
  2226                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2227 00005156 66A1[78680000]      <1> 	mov	ax, [ii]
  2228 0000515C 66A3[82680000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2229                              <1> 
  2230                              <1> 	; 11/01/2022
  2231 00005162 BB[58770000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2232                              <1> sysmnt_3: ;1:
  2233                              <1>         ;cmp	byte [ebx+1], 0
  2234                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2235                              <1> 			   ; / dismountable device set?
  2236                              <1>         ;jna	short sysmnt_4		
  2237                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2238                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2239                              <1> 	;jmp	short sysmnt_3
  2240                              <1> sysmnt_4:   
  2241 00005167 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2242 00005168 A2[7D680000]        <1> 	mov	[mdev], al
  2243                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2244 0000516D 8803                <1> 	mov	[ebx], al
  2245                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2246                              <1> 			      ; / of the I/O queue entry
  2247                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2248                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2249 0000516F 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2250                              <1> 		; bis $2000,sb1 / set the read bit
  2251                              <1> 	; Retro UNIX 386 v1 modification : 
  2252                              <1> 	;	32 bit block number at buffer header offset 4
  2253 00005174 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2254 0000517B E859060000          <1> 	call 	diskio
  2255 00005180 7345                <1> 	jnc	short sysmnt_5
  2256 00005182 31C0                <1> 	xor 	eax, eax
  2257 00005184 66A3[80680000]      <1> 	mov	[mnti], ax ; 0
  2258 0000518A A2[7D680000]        <1> 	mov	[mdev], al ; 0
  2259                              <1> 	;mov	[cdev], al ; 0
  2260                              <1> 	; 08/02/2022
  2261 0000518F 803D[00690000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2262 00005196 7508                <1> 	jne	short sysmnt_err3
  2263                              <1> 	; yes, clear [u.brwdev] for next check
  2264                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2265 00005198 FE05[00690000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2266 0000519E EB0A                <1> 	jmp	short sysmnt_err4
  2267                              <1> sysmnt_err3:	; 08/02/2022
  2268                              <1> 	; no, set [u.error] to disk read error
  2269 000051A0 C705[ED680000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2269 000051A8 0000                <1>
  2270                              <1> sysmnt_err4:
  2271                              <1> 	; 08/02/2022
  2272                              <1> 	; 14/11/2015
  2273 000051AA FEC8                <1> 	dec 	al
  2274 000051AC 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2275 000051AE FEC0                <1> 	inc	al
  2276 000051B0 48                  <1> 	dec	eax
  2277 000051B1 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2278 000051B4 E959E1FFFF          <1> 	jmp	error
  2279                              <1> sysmnt_invd:
  2280                              <1> 	; 08/02/2022
  2281 000051B9 C705[ED680000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2281 000051C1 0000                <1>
  2282                              <1> 				 ;'invalid fs/superblock !' error
  2283 000051C3 30C0                <1> 	xor	al, al
  2284 000051C5 EBE3                <1> 	jmp	short sysmnt_err4	
  2285                              <1> 
  2286                              <1> sysmnt_5:
  2287                              <1> 	; 08/02/2022
  2288                              <1> 	; 11/01/2022 (BugFix)
  2289                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2290                              <1> 	; (Following check is needed to prevent mounting an
  2291                              <1> 	; invalid file system (invalid super block).
  2292                              <1> 	; 
  2293 000051C7 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2294 000051CA C0E002              <1> 	shl	al, 2 ; 4*index
  2295 000051CD 8B88[FE5F0000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2296 000051D3 C1E903              <1> 	shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2297                              <1> 	; ecx = number of free map bytes (required)
  2298                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2299 000051D6 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2300                              <1> 	; edx = number of free blocks map bytes
  2301                              <1> 	;shl	edx, 3 ; convert free map bytes to free map bits
  2302                              <1> 	; 07/02/2022
  2303                              <1> 	;xor	al, al ; 08/02/2022
  2304 000051DA 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2305                              <1> 			 ; (in sectors), if they are not equal
  2306                              <1> 			 ; the disk to be mounted is an...	
  2307 000051DC 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2308                              <1> 			 ; (which has not got a valid super block)
  2309                              <1> 	;
  2310 000051DE C6430100            <1> 	mov	byte [ebx+1], 0
  2311                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2312                              <1> ;sysmnt_6: ;1:
  2313                              <1> 	;;cmp	byte [sb1+1], 0
  2314                              <1> 		; tstb sb1+1 / done reading?
  2315                              <1>    	;;jna	sysret
  2316                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2317                              <1> 	;;jmp	short sysmnt_6
  2318                              <1> 		; bne 1b / no, wait
  2319                              <1>         	; br sysreta / yes
  2320 000051E2 E94BE1FFFF          <1> 	jmp	sysret
  2321                              <1> 
  2322                              <1> sysumount: ; / special dismount file system
  2323                              <1> 	; 15/05/2022
  2324                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2325                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2326                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2327                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2328                              <1> 	;
  2329                              <1> 	; 04/11/2013
  2330                              <1> 	; 09/07/2013
  2331                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2332                              <1> 	; indicated as an argument is no longer contain a removable
  2333                              <1> 	; file system. 'getspl' gets the device number of the special
  2334                              <1> 	; file. If no file system was mounted on that device an error
  2335                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2336                              <1> 	; to 'sysret'.
  2337                              <1> 	;
  2338                              <1> 	; Calling sequence:
  2339                              <1> 	;	sysmount; special
  2340                              <1> 	; Arguments:
  2341                              <1> 	;	special - special file to dismount (device)
  2342                              <1> 	;
  2343                              <1> 	; Inputs: - 
  2344                              <1> 	; Outputs: -
  2345                              <1> 	; ...............................................................
  2346                              <1> 	;				
  2347                              <1> 	; Retro UNIX 8086 v1 modification: 
  2348                              <1> 	;       'sysumount' system call has one argument; so,
  2349                              <1> 	;	* Single argument, special is pointed to by BX register
  2350                              <1> 	;
  2351                              <1> 	
  2352                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2353                              <1> 	;call	arg
  2354                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2355 000051E7 891D[B0680000]      <1>         mov	[u.namep], ebx
  2356 000051ED E86F000000          <1> 	call	getspl
  2357                              <1> 		; jsr r0,getspl / get the device number in r1
  2358                              <1> 
  2359                              <1> 	;;;
  2360                              <1> 	; 09/05/2022 - Erdogan Tan
  2361                              <1> 	; (I have added [mnti] check because
  2362                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2363                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2364                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2365                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2366 000051F2 66833D[80680000]00  <1> 	cmp	word [mnti], 0
  2367 000051FA 767D                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2368                              <1> 	;;;
  2369                              <1> 
  2370 000051FC 3A05[7D680000]      <1> 	cmp	al, [mdev]
  2371                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2372 00005202 7575                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2373                              <1> 	;jne	error
  2374                              <1>         	; bne errora / no error
  2375 00005204 30C0                <1> 	xor	al, al ; ah = 0
  2376                              <1> sysumnt_0: ;1:
  2377                              <1>      	; 11/01/2022
  2378                              <1> 	;cmp 	[sb1+1], al ; 0
  2379                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2380                              <1> 	;		   ; / (inhibit bit set)?
  2381                              <1> 	;jna	short sysumnt_1		
  2382                              <1> 	;	; bne 1b / yes, wait
  2383                              <1> 	;call	idle ; (wait for hardware interrupt)
  2384                              <1> 	;jmp	short sysumnt_0
  2385                              <1> sysumnt_1:        
  2386                              <1> 	; 15/05/2022
  2387                              <1> 	; change user's current directory to mounting directory
  2388                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2389 00005206 3805[E2680000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2390 0000520C 7643                <1> 	jna	short sysumnt_4
  2391                              <1> 	;;;
  2392                              <1> 	; 15/05/2022
  2393                              <1> 	; It is needed to change the parent process's current
  2394                              <1> 	; directory because shell runs (/etc/umount) 
  2395                              <1> 	; as child process.
  2396 0000520E 31DB                <1> 	xor	ebx, ebx 
  2397 00005210 8A1D[E7680000]      <1> 	mov	bl, [u.uno]
  2398 00005216 D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2399 00005218 81C3[D2650000]      <1> 	add	ebx, p.ppid-2
  2400 0000521E 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2401 00005221 BE[B4650000]        <1> 	mov	esi, p.pid
  2402 00005226 29C9                <1> 	sub	ecx, ecx
  2403 00005228 B110                <1> 	mov	cl, nproc ; 16  
  2404                              <1> sysumnt_2:	
  2405 0000522A 66AD                <1> 	lodsw
  2406 0000522C 6639D0              <1> 	cmp	ax, dx
  2407 0000522F 7402                <1> 	je	short sysumnt_3
  2408 00005231 E2F7                <1> 	loop	sysumnt_2
  2409                              <1> sysumnt_3:
  2410 00005233 31C0                <1> 	xor	eax, eax
  2411 00005235 81EE[B4650000]      <1> 	sub	esi, p.pid
  2412 0000523B D1E6                <1> 	shl	esi, 1
  2413 0000523D 8B9E[20660000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2414                              <1> 	; ebx points to user (u) structure in upage
  2415 00005243 668B15[80680000]    <1> 	mov	dx, [mnti]
  2416                              <1> 	;mov	[u.cdir], dx
  2417                              <1> 	;mov	[u.cdrv], al ; 0
  2418 0000524A 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2419 0000524E 884352              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2420                              <1> 	;;;
  2421                              <1> sysumnt_4: 
  2422 00005251 A2[7D680000]        <1> 	mov	[mdev], al ; 0
  2423                              <1> 	     	; clr mntd / no, clear these
  2424 00005256 66A3[80680000]      <1>    	mov	[mnti], ax ; 0
  2425                              <1>         	; clr mnti
  2426                              <1> 
  2427                              <1> 	;; 15/05/2022
  2428                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2429                              <1> 	;mov	ax, dx  ; [u.cdir]
  2430                              <1> 	;call	iget
  2431                              <1> 
  2432 0000525C E9D1E0FFFF          <1>         jmp	sysret
  2433                              <1> 		; br sysreta / return
  2434                              <1> 
  2435                              <1> getspl: ; / get device number from a special file name
  2436 00005261 E8B9EFFFFF          <1> 	call	namei
  2437                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2438                              <1> 		       ; ax = 0 -> file not found 	
  2439                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2440                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2441 00005266 7305                <1> 	jnc	short getspl_0
  2442 00005268 E9D4FEFFFF          <1> 	jmp	sysmnt_err2 ; 'file not found !' error
  2443                              <1> getspl_0:
  2444                              <1> 	;jz	error
  2445                              <1> 	;jc	error
  2446                              <1> 		; jsr r0,namei / get the i-number of the special file
  2447                              <1>                 ; br errora / no such file
  2448 0000526D 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2449                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2450                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2451 00005271 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2452                              <1> 	;jc	error
  2453                              <1> 		; ble errora / less than 0?  yes, error
  2454 00005273 6683F805            <1>         cmp	ax, 5 ;
  2455                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2456                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2457                              <1> 	;;ja	error
  2458                              <1> 		; bgt errora / yes, error
  2459                              <1> 	; 11/01/2022
  2460 00005277 760F                <1> 	jna	short getspl_retn
  2461                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2462                              <1> ;iopen_retn:
  2463                              <1> ;	retn
  2464                              <1> 		; rts r0 / return with device number in r1
  2465                              <1> sysmnt_err0:
  2466 00005279 C705[ED680000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2466 00005281 0000                <1>
  2467 00005283 E98AE0FFFF          <1> 	jmp	error
  2468                              <1> 
  2469                              <1> getspl_retn:
  2470                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2471                              <1> 	; 11/01/2022
  2472                              <1> iopen_retn:
  2473 00005288 C3                  <1> 	retn
  2474                              <1> 
  2475                              <1> iopen:	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2476                              <1> 	;		(Printer initialization)
  2477                              <1> 	; 11/01/2022
  2478                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2479                              <1> 	; 19/05/2015
  2480                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2481                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2482                              <1> 	;
  2483                              <1> 	; open file whose i-number is in r1
  2484                              <1> 	; 
  2485                              <1> 	; INPUTS ->
  2486                              <1> 	;    r1 - inode number
  2487                              <1> 	; OUTPUTS ->
  2488                              <1> 	;    file's inode in core	
  2489                              <1> 	;    r1 - inode number (positive)
  2490                              <1> 	;
  2491                              <1> 	; ((AX = R1))
  2492                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2493                              <1> 	;        
  2494                              <1> ; / open file whose i-number is in r1
  2495 00005289 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2496                              <1> 		; tst r1 / write or read access?
  2497 0000528C 7568                <1>         jnz	short iopen_2
  2498                              <1> 		; blt 2f / write, go to 2f
  2499 0000528E B202                <1> 	mov	dl, 2 ; read access
  2500 00005290 E86EF8FFFF          <1> 	call	access
  2501                              <1>         	; jsr r0,access; 2 
  2502                              <1> 	; / get inode into core with read access
  2503                              <1> 	; DL=2
  2504                              <1> iopen_0:
  2505 00005295 6683F828            <1>         cmp	ax, 40
  2506                              <1> 		; cmp r1,$40. / is it a special file
  2507 00005299 77ED                <1>         ja	short iopen_retn
  2508                              <1> 		; bgt  3f / no. 3f
  2509 0000529B 50                  <1> 	push	eax ; 08/01/2022
  2510                              <1> 	;push	ax
  2511                              <1> 		; mov r1,-(sp) / yes, figure out
  2512 0000529C 0FB6D8              <1> 	movzx	ebx, al
  2513 0000529F C0E302              <1> 	shl	bl, 2 ; * 4 ; 08/01/2022
  2514                              <1> 	;shl	bx, 2
  2515                              <1> 		; asl r1
  2516 000052A2 81C3[A6520000]      <1>         add     ebx, iopen_1 - 4
  2517 000052A8 FF23                <1> 	jmp	dword [ebx]
  2518                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2519                              <1> iopen_1: ; 1:
  2520 000052AA [0E530000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2521                              <1>  		 ;otty / tty ; r1=2
  2522                              <1>         	 ;oppt / ppt ; r1=4
  2523 000052AE [C6530000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2524                              <1> 		 ;sret / mem ; r1=6
  2525                              <1> 		 ;sret / rf0
  2526                              <1>         	 ;sret / rk0
  2527                              <1>         	 ;sret / tap0
  2528                              <1>         	 ;sret / tap1
  2529                              <1>         	 ;sret / tap2
  2530                              <1>         	 ;sret / tap3
  2531                              <1>         	 ;sret / tap4
  2532                              <1>         	 ;sret / tap5
  2533                              <1>         	 ;sret / tap6
  2534                              <1>         	 ;sret / tap7
  2535 000052B2 [C6530000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2536 000052B6 [C6530000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2537 000052BA [C6530000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2538 000052BE [C6530000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2539 000052C2 [C6530000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2540 000052C6 [C6530000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2541                              <1> 	;;dd	error ; lpr, AX = 9 (error !)
  2542                              <1>         ;dd	sret ; lpr, AX = 9 (runix)
  2543                              <1> 	; 13/06/2022 - (lpt_init)
  2544 000052CA [92540000]          <1>         dd	ejec ; lpr, AX = 9 (runix)
  2545 000052CE [1F530000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2546                              <1> 		 ;ocvt / tty0
  2547 000052D2 [1F530000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2548                              <1> 		 ;ocvt / tty1
  2549 000052D6 [1F530000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2550                              <1> 		 ;ocvt / tty2
  2551 000052DA [1F530000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2552                              <1> 		 ;ocvt / tty3
  2553 000052DE [1F530000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2554                              <1> 		 ;ocvt / tty4
  2555 000052E2 [1F530000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2556                              <1> 		 ;ocvt / tty5
  2557 000052E6 [1F530000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2558                              <1> 		 ;ocvt / tty6
  2559 000052EA [1F530000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2560                              <1> 		 ;ocvt / tty7
  2561 000052EE [1F530000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2562                              <1> 		 ;error / crd
  2563 000052F2 [1F530000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2564                              <1> 
  2565                              <1> iopen_2: ; 2: / check open write access
  2566 000052F6 66F7D8              <1> 	neg	ax
  2567                              <1> 		;neg r1 / make inode number positive
  2568 000052F9 B201                <1> 	mov	dl, 1 ; write access
  2569 000052FB E803F8FFFF          <1> 	call	access
  2570                              <1> 		;jsr r0,access; 1 / get inode in core
  2571                              <1> 	; DL=1
  2572                              <1> 	; 11/01/2022
  2573 00005300 F605[95650000]40    <1> 	test	byte [i.flgs+1], 40h
  2574                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2575                              <1>  		; bit $40000,i.flgs / is it a directory?
  2576 00005307 748C                <1> 	jz	short iopen_0
  2577                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2578                              <1> 	;jmp	error ; permission denied !
  2579 00005309 E96BFFFFFF          <1> 	jmp	sysmnt_err0
  2580                              <1> 	;;jnz	error		
  2581                              <1>        		; bne 2f / yes, transfer (error)
  2582                              <1>         ;;jmp	short iopen_0
  2583                              <1> 	;cmp	ax, 40
  2584                              <1> 		; cmp r1,$40. / no, is it a special file?
  2585                              <1>         ;ja	short iopen_2
  2586                              <1> 		; bgt 3f / no, return
  2587                              <1> 	;push	ax
  2588                              <1> 		; mov r1,-(sp) / yes
  2589                              <1> 	;movzx	ebx, al
  2590                              <1> 	;shl	bx, 1
  2591                              <1> 		; asl r1
  2592                              <1> 	;add	ebx, ipen_3 - 2
  2593                              <1> 	;jmp	dword [ebx]
  2594                              <1> 		; jmp *1f-2(r1) / figure out 
  2595                              <1> 			; / which special file it is and transfer
  2596                              <1> ;iopen_3: ; 1:
  2597                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2598                              <1>  		 ;otty / tty ; r1=2
  2599                              <1>         	 ;leadr / ppt ; r1=4
  2600                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2601                              <1> 		 ;sret / mem ; r1=6
  2602                              <1> 		 ;sret / rf0
  2603                              <1>         	 ;sret / rk0
  2604                              <1>         	 ;sret / tap0
  2605                              <1>         	 ;sret / tap1
  2606                              <1>         	 ;sret / tap2
  2607                              <1>         	 ;sret / tap3
  2608                              <1>         	 ;sret / tap4
  2609                              <1>         	 ;sret / tap5
  2610                              <1>         	 ;sret / tap6
  2611                              <1>         	 ;sret / tap7
  2612                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2613                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2614                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2615                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2616                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2617                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2618                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2619                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2620                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2621                              <1> 		 ;ocvt / tty0
  2622                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2623                              <1> 		 ;ocvt / tty1
  2624                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2625                              <1> 		 ;ocvt / tty2
  2626                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2627                              <1> 		 ;ocvt / tty3
  2628                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2629                              <1> 		 ;ocvt / tty4
  2630                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2631                              <1> 		 ;ocvt / tty5
  2632                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2633                              <1> 		 ;ocvt / tty6
  2634                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2635                              <1> 		 ;ocvt / tty7
  2636                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2637                              <1> 		 ;/ ejec / lpr
  2638                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2639                              <1> 
  2640                              <1> otty: ;/ open console tty for reading or writing
  2641                              <1> 	; 03/03/2022
  2642                              <1> 	; 02/03/2022
  2643                              <1> 	; 26/02/2022
  2644                              <1> 	; 09/02/2022
  2645                              <1> 	; 06/02/2022
  2646                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2647                              <1> 	; 16/11/2015
  2648                              <1> 	; 12/11/2015
  2649                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2650                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2651                              <1> 	; 16/07/2013
  2652                              <1> 	; Retro UNIX 8086 v1 modification:
  2653                              <1> 	;  If a tty is open for read or write by
  2654                              <1> 	;     a process (u.uno), only same process can open
  2655                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2656                              <1> 	;
  2657                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2658                              <1> 	;
  2659 0000530E 0FB61D[E7680000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2660 00005315 8A83[F3650000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2661                              <1> 	; 13/01/2014
  2662                              <1> 	;jmp	short ottyp
  2663                              <1> 	; 26/02/2022
  2664 0000531B 88C4                <1> 	mov	ah, al
  2665 0000531D EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2666                              <1> ocvt:
  2667 0000531F 2C0A                <1> 	sub	al, 10
  2668                              <1> ;ottyp:	; (call from sysstty)
  2669                              <1> 	; 08/01/2022
  2670 00005321 31DB                <1> 	xor	ebx, ebx
  2671                              <1> ottyp:	; (ebx < 256) ; 06/02/2022
  2672                              <1> 	; 26/02/2022
  2673 00005323 B4FF                <1> 	mov	ah, 0FFh
  2674                              <1> ottypc:
  2675                              <1> 	; 03/03/2022
  2676                              <1> 	; 26/02/2022
  2677                              <1> 	; 09/02/2022
  2678                              <1> 	; 08/01/2022
  2679                              <1> 	; 16/11/2015
  2680                              <1> 	; 12/11/2015
  2681                              <1> 	; 18/05/2015 (32 bit modifications)
  2682                              <1> 	; 06/12/2013 - 13/07/2014
  2683 00005325 88C6                <1> 	mov	dh, al ; tty number
  2684                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2685                              <1> 	; 08/01/2022
  2686 00005327 88C3                <1> 	mov	bl, al
  2687 00005329 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2688                              <1> 	; 26/01/2014	
  2689 0000532B 81C3[24650000]      <1> 	add 	ebx, ttyl
  2690 00005331 668B0B              <1> 	mov 	cx, [ebx]
  2691                              <1> 		   ; CL = lock value (0 or process number)
  2692                              <1> 		   ; CH = open count 
  2693 00005334 20C9                <1> 	and 	cl, cl
  2694                              <1> 	; 13/01/2014
  2695                              <1> 	;jz 	short otty_ret
  2696                              <1> 	; 08/01/2022
  2697 00005336 7447                <1> 	jz 	short ottys_0
  2698                              <1> 	;
  2699                              <1> 	; 16/11/2015
  2700 00005338 3A0D[E7680000]      <1> 	cmp 	cl, [u.uno]
  2701 0000533E 746E                <1> 	je	short ottys_3
  2702                              <1> 	;
  2703                              <1> 	;
  2704                              <1> 	; 26/02/2022
  2705                              <1> 	; (is it the console tty of the current process?)
  2706                              <1> 	; ((fast check/permit for console tty open function))
  2707 00005340 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2708 00005342 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2709                              <1> 	;
  2710                              <1> 	; 26/02/2022
  2711                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2712                              <1> 	;shl 	bl, 1
  2713                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2714                              <1> 	;;movzx ebx, byte [u.uno]
  2715                              <1> 	;mov	bl, [u.uno]
  2716                              <1> 	;shl 	bl, 1
  2717                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2718                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2719                              <1> 	; 26/02/2022 (BugFix) ; *
  2720 00005344 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2721 00005347 D1E6                <1> 	shl 	esi, 1
  2722 00005349 668B86[B2650000]    <1> 	mov 	ax, [esi+p.pid-2]
  2723 00005350 96                  <1> 	xchg	esi, eax
  2724 00005351 A0[E7680000]        <1> 	mov	al, [u.uno]
  2725 00005356 D0E0                <1> 	shl 	al, 1
  2726 00005358 663BB0[D2650000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2727 0000535F 744D                <1> 	je 	short ottys_3 ; *
  2728                              <1> 	; 26/02/2022
  2729                              <1> 	; check console tty of the process
  2730                              <1> 	; (open permission must be given if the -requested- tty is
  2731                              <1> 	;  console tty of current process)
  2732 00005361 D0E8                <1> 	shr	al, 1
  2733 00005363 38B0[F3650000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2734 00005369 7443                <1> 	je 	short ottys_3
  2735                              <1> 	;
  2736                              <1> 	; the tty is locked by another process
  2737                              <1> 	; except the parent process (p.ppid)
  2738                              <1>         ;
  2739                              <1> 	; 09/02/2022
  2740                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2741                              <1> 	;		; permission denied ! error
  2742                              <1> otty_err: ; 13/01/2014
  2743                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2744                              <1> 	;;jnz	error
  2745                              <1> 	; 05/12/2021
  2746                              <1> 	;jz	short otty_stc_retn
  2747                              <1> 	;jmp	error
  2748                              <1> 	; 09/02/2022
  2749 0000536B 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2750 0000536E 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2751                              <1> 	; iopen (dl=1 or dl=2)
  2752 00005370 C705[ED680000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2752 00005378 0000                <1>
  2753                              <1> 			; permission denied ! error
  2754 0000537A E993DFFFFF          <1> 	jmp	error
  2755                              <1> ;otty_stc_retn:
  2756                              <1> 	;stc
  2757                              <1> 	;retn
  2758                              <1> ottys_0:
  2759                              <1> 	; 08/01/2022
  2760                              <1> otty_ret: 
  2761                              <1> 	; 13/01/2014
  2762 0000537F 80FE07              <1> 	cmp 	dh, 7
  2763 00005382 7624                <1> 	jna	short ottys_2
  2764                              <1> 	; 16/11/2015
  2765                              <1> com_port_check:
  2766 00005384 BE[42650000]        <1> 	mov	esi, com1p
  2767 00005389 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2768 0000538C 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2769 0000538E 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2770                              <1> ottys_1:
  2771                              <1> 	; 12/11/2015
  2772 0000538F 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2773 00005392 7714                <1> 	ja	short com_port_ready
  2774                              <1> 	;
  2775                              <1> 	; 09/02/2022
  2776 00005394 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2777 00005397 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2778 00005399 C705[ED680000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2778 000053A1 0000                <1>
  2779                              <1> 			   ; device not ready ! error
  2780                              <1> 	;jmp	short otty_err
  2781 000053A3 E96ADFFFFF          <1> 	jmp	error
  2782                              <1> com_port_ready:
  2783                              <1> ottys_2:
  2784                              <1> 	; 02/03/2022
  2785                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2786                              <1> 	;jnz	short ottys_3
  2787 000053A8 8A0D[E7680000]      <1> 	mov	cl, [u.uno]
  2788                              <1> ottys_3:
  2789 000053AE FEC5                <1> 	inc 	ch
  2790 000053B0 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2791                              <1> 	; 06/12/2013
  2792 000053B3 FEC6                <1> 	inc	dh ; tty number + 1
  2793 000053B5 BB[C8680000]        <1> 	mov	ebx, u.ttyp
  2794                              <1> 	; 13/01/2014
  2795 000053BA F6C202              <1> 	test	dl, 2 ; open for read sign
  2796 000053BD 7501                <1> 	jnz	short ottys_4
  2797 000053BF 43                  <1> 	inc	ebx
  2798                              <1> ottys_4:
  2799                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2800 000053C0 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2801                              <1> 	; 09/02/2022
  2802 000053C2 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2803 000053C4 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2804                              <1> sret:
  2805                              <1> 	;pop 	ax
  2806 000053C6 58                  <1> 	pop	eax ; 08/01/2022
  2807                              <1> otty_retn:	; 09/02/2022
  2808                              <1> iclose_retn:	
  2809 000053C7 C3                  <1> 	retn
  2810                              <1> 
  2811                              <1> 	;
  2812                              <1> 	; Original UNIX v1 'otty' routine:
  2813                              <1> 	;	
  2814                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2815                              <1>         ;                 / reader status reg
  2816                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2817                              <1>         ;                 / punch status reg
  2818                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2819                              <1>         ;                          / console tty buffer
  2820                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2821                              <1>         ;            / console tty
  2822                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2823                              <1>         ;             / buffer header
  2824                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2825                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2826                              <1>         ;                 / tty
  2827                              <1>         ;br     sret / ?
  2828                              <1> ;sret:
  2829                              <1> 		;clr *$ps / set processor priority to zero
  2830                              <1> ;	pop	ax
  2831                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2832                              <1> ;3:
  2833                              <1> ;	retn
  2834                              <1>         	;rts r0
  2835                              <1> 	
  2836                              <1> ;ocvt:	; < open tty >
  2837                              <1> 	; 13/01/2014
  2838                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2839                              <1> 	; 24/09/2013 consistency check -> ok
  2840                              <1> 	; 16/09/2013
  2841                              <1> 	; 03/09/2013
  2842                              <1> 	; 27/08/2013
  2843                              <1> 	; 16/08/2013
  2844                              <1> 	; 16/07/2013
  2845                              <1> 	; 27/05/2013
  2846                              <1> 	; 21/05/2013
  2847                              <1> 	;
  2848                              <1> 	; Retro UNIX 8086 v1 modification !
  2849                              <1> 	; 
  2850                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2851                              <1> 	;	(exactly different than this one)
  2852                              <1> 	;	was in 'u9.s' file.
  2853                              <1> 	;
  2854                              <1> 	; 16/07/2013
  2855                              <1> 	; Retro UNIX 8086 v1 modification:
  2856                              <1> 	;  If a tty is open for read or write by
  2857                              <1> 	;     a process (u.uno), only same process can open
  2858                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2859                              <1> 	;
  2860                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2861                              <1> 
  2862                              <1> 	; 16/09/2013
  2863                              <1> 	; sub 	al, 10
  2864                              <1> 	
  2865                              <1> 	; 06/12/2013
  2866                              <1> 	;cmp	al, 7
  2867                              <1>         ;jna     short ottyp
  2868                              <1> 	; 13/01/2014
  2869                              <1> 	;jmp	short ottyp
  2870                              <1> 
  2871                              <1> ;oppt: / open paper tape for reading or writing
  2872                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2873                              <1> ;        tstb   pptiflg / is file already open
  2874                              <1> ;        bne    2f / yes, branch
  2875                              <1> ;1:
  2876                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2877                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2878                              <1> ;               br .+4 / for paper tape input and place in free list
  2879                              <1> ;        br     1b
  2880                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2881                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2882                              <1> ;        br     sret
  2883                              <1> ;2:
  2884                              <1> ;        jmp    error / file already open
  2885                              <1> 
  2886                              <1> iclose:
  2887                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2888                              <1> 	; 19/05/2015
  2889                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2890                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2891                              <1> 	;
  2892                              <1> 	; close file whose i-number is in r1
  2893                              <1> 	; 
  2894                              <1> 	; INPUTS ->
  2895                              <1> 	;    r1 - inode number
  2896                              <1> 	; OUTPUTS ->
  2897                              <1> 	;    file's inode in core	
  2898                              <1> 	;    r1 - inode number (positive)
  2899                              <1> 	;
  2900                              <1> 	; ((AX = R1))
  2901                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2902                              <1> 	;        
  2903                              <1> ;/ close file whose i-number is in r1
  2904 000053C8 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2905 000053CA F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2906                              <1> 		; tst r1 / test i-number
  2907                              <1>         ;jnz	short iclose_2
  2908                              <1> 		; blt 2f / if neg., branch
  2909 000053CD 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2910                              <1> 	; 16/07/2013 
  2911 000053CF 66F7D8              <1> 	neg	ax ; make it positive
  2912                              <1> 	; 12/01/2014
  2913 000053D2 FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2914                              <1> iclose_0:
  2915 000053D4 6683F828            <1> 	cmp	ax, 40
  2916                              <1> 		; cmp r1,$40. / is it a special file
  2917 000053D8 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2918                              <1> 		; bgt 3b / no, return
  2919                              <1> 	; 12/01/2014
  2920                              <1> 	; DL=2 -> special file was opened for reading
  2921                              <1> 	; DL=1 -> special file was opened for writing
  2922 000053DA 50                  <1> 	push	eax ; 08/01/2022
  2923                              <1> 	;push	ax
  2924                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2925 000053DB 0FB6D8              <1> 	movzx	ebx, al
  2926                              <1> 	; 08/01/2022
  2927 000053DE C0E302              <1> 	shl	bl, 2
  2928                              <1> 	;shl	bx, 2
  2929                              <1> 		; asl r1
  2930 000053E1 81C3[E5530000]      <1> 	add	ebx, iclose_1 - 4
  2931 000053E7 FF23                <1> 	jmp	dword [ebx]
  2932                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2933                              <1> iclose_1 :
  2934 000053E9 [35540000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2935 000053ED [90540000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2936 000053F1 [90540000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2937 000053F5 [90540000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2938 000053F9 [90540000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2939 000053FD [90540000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2940 00005401 [90540000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2941 00005405 [90540000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2942 00005409 [90540000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2943                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2944                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2945 0000540D [44540000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2946 00005411 [44540000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2947 00005415 [44540000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2948 00005419 [44540000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2949 0000541D [44540000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2950 00005421 [44540000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2951 00005425 [44540000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2952 00005429 [44540000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2953 0000542D [44540000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2954 00005431 [44540000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2955                              <1> 
  2956                              <1> 	; 1:
  2957                              <1> 	;        ctty   / tty
  2958                              <1> 	;        cppt   / ppt
  2959                              <1> 	;        sret   / mem
  2960                              <1> 	;        sret   / rf0
  2961                              <1> 	;        sret   / rk0
  2962                              <1> 	;        sret   / tap0
  2963                              <1> 	;        sret   / tap1
  2964                              <1> 	;        sret   / tap2
  2965                              <1> 	;        sret   / tap3
  2966                              <1> 	;        sret   / tap4
  2967                              <1> 	;        sret   / tap5
  2968                              <1> 	;        sret   / tap6
  2969                              <1> 	;        sret   / tap7
  2970                              <1> 	;        ccvt   / tty0
  2971                              <1> 	;        ccvt   / tty1
  2972                              <1> 	;        ccvt   / tty2
  2973                              <1> 	;        ccvt   / tty3
  2974                              <1> 	;        ccvt   / tty4
  2975                              <1> 	;        ccvt   / tty5
  2976                              <1> 	;        ccvt   / tty6
  2977                              <1> 	;        ccvt   / tty7
  2978                              <1> 	;        error / crd
  2979                              <1> 
  2980                              <1> ;iclose_2: ; 2: / negative i-number
  2981                              <1> 	;neg	ax
  2982                              <1> 		;neg r1 / make it positive
  2983                              <1> 	;cmp	ax, 40
  2984                              <1> 		;cmp r1,$40. / is it a special file?
  2985                              <1>         ;ja	short @b
  2986                              <1> 		;bgt    3b / no. return
  2987                              <1> 	;push	ax
  2988                              <1> 		;mov r1,-(sp)
  2989                              <1> 	;movzx	ebx, al
  2990                              <1> 	;shl	bx, 1
  2991                              <1> 		;asl r1 / yes. compute jump address and transfer
  2992                              <1> 	;add	ebx, iclose_3 - 2
  2993                              <1> 	;jmp	dword [ebx]
  2994                              <1> 		;jmp *1f-2(r1) / figure out 
  2995                              <1> ;iclose_3:
  2996                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2997                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2998                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2999                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  3000                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  3001                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  3002                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  3003                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  3004                              <1> 	 ;dd	sret ; lpr, AX = 9	
  3005                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  3006                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  3007                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  3008                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  3009                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  3010                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  3011                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  3012                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  3013                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  3014                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  3015                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  3016                              <1> 	
  3017                              <1> 	;1:
  3018                              <1> 	;      	ctty   / tty
  3019                              <1> 	;       leadr  / ppt
  3020                              <1> 	;       sret   / mem
  3021                              <1> 	;       sret   / rf0
  3022                              <1> 	;       sret   / rk0
  3023                              <1> 	;       sret   / tap0
  3024                              <1> 	;       sret   / tap1
  3025                              <1> 	;       sret   / tap2
  3026                              <1> 	;       sret   / tap3
  3027                              <1> 	;       sret   / tap4
  3028                              <1> 	;       sret   / tap5
  3029                              <1> 	;       sret   / tap6
  3030                              <1> 	;       sret   / tap7
  3031                              <1> 	;       ccvt   / tty0
  3032                              <1> 	;       ccvt   / tty1
  3033                              <1> 	;       ccvt   / tty2
  3034                              <1> 	;       ccvt   / tty3
  3035                              <1> 	;       ccvt   / tty4
  3036                              <1> 	;       ccvt   / tty5
  3037                              <1> 	;       ccvt   / tty6
  3038                              <1> 	;       ccvt   / tty7
  3039                              <1> 	;/      ejec   / lpr
  3040                              <1> 
  3041                              <1> ctty: ; / close console tty
  3042                              <1> 	; 26/02/2022
  3043                              <1> 	; 09/02/2022
  3044                              <1> 	; 06/02/2022
  3045                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3046                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3047                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  3048                              <1> 	;
  3049                              <1> 	; Retro UNIX 8086 v1 modification !
  3050                              <1> 	; (DL = 2 -> it is open for reading)
  3051                              <1> 	; (DL = 1 -> it is open for writing)
  3052                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3053                              <1> 	;
  3054                              <1> 	; 06/12/2013
  3055 00005435 0FB61D[E7680000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3056 0000543C 8A83[F3650000]      <1>         mov     al, [ebx+p.ttyc-1]
  3057                              <1> 	; 13/01/2014
  3058                              <1> 	;jmp	short cttyp
  3059                              <1> 	; 06/02/2022
  3060 00005442 EB04                <1> 	jmp	short ctty_0
  3061                              <1> ccvt:
  3062 00005444 2C0A                <1> 	sub 	al, 10
  3063                              <1> cttyp:	; (call from sysstty)
  3064                              <1> 	; 08/01/2022
  3065 00005446 31DB                <1> 	xor	ebx, ebx
  3066                              <1> ctty_0: ; (ebx < 256)  ; 06/02/2022
  3067                              <1> 	; 08/01/2022
  3068                              <1> 	; 18/05/2015 (32 bit modifications)
  3069                              <1> 	; 16/08/2013 - 26/01/2014
  3070                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3071                              <1> 	; 08/01/2022
  3072 00005448 88C3                <1> 	mov	bl, al
  3073 0000544A D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3074                              <1> 	; 26/01/2014
  3075 0000544C 81C3[24650000]      <1> 	add 	ebx, ttyl
  3076 00005452 88C6                <1> 	mov 	dh, al ; tty number
  3077 00005454 668B03              <1> 	mov 	ax, [ebx]
  3078                              <1> 		   ; AL = lock value (0 or process number)
  3079                              <1> 		   ; AH = open count 
  3080 00005457 20E4                <1> 	and 	ah, ah
  3081 00005459 7514                <1> 	jnz	short ctty_ret
  3082                              <1>   	; 09/02/2022
  3083 0000545B 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3084 0000545E 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3085                              <1> 	; iclose (dl=1 or dl=2)
  3086 00005460 C705[ED680000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3086 00005468 0000                <1>
  3087                              <1> 			; device not open ! error
  3088                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3089 0000546A E9A3DEFFFF          <1> 	jmp	error
  3090                              <1> 	; 26/01/2014
  3091                              <1> ctty_ret:
  3092 0000546F FECC                <1> 	dec 	ah ; decrease open count
  3093 00005471 7502                <1> 	jnz	short ctty_1
  3094 00005473 30C0                <1> 	xor	al, al ; unlock/free tty
  3095                              <1> ctty_1:
  3096 00005475 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3097                              <1> 	;
  3098 00005478 BB[C8680000]        <1> 	mov	ebx, u.ttyp
  3099                              <1> 	;test	dl, 1 ; open for write sign
  3100                              <1> 	;jz	short ctty_2
  3101                              <1> 	; 26/02/2022
  3102 0000547D F6C202              <1> 	test	dl, 2 ; open for read sign
  3103 00005480 7501                <1> 	jnz	short ctty_2
  3104 00005482 43                  <1> 	inc	ebx
  3105                              <1> ctty_2:
  3106 00005483 FEC6                <1> 	inc	dh ; tty number + 1
  3107 00005485 3A33                <1> 	cmp	dh, [ebx]
  3108                              <1> 	;jne	short cret
  3109 00005487 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3110                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3111 00005489 C60300              <1> 	mov	byte [ebx], 0
  3112                              <1> ctty_3:
  3113                              <1> 	; 09/02/2022
  3114 0000548C 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3115 0000548E 7401                <1> 	jz	short ctty_4
  3116                              <1> cret:
  3117                              <1> 	;pop	ax
  3118                              <1> 	; 08/01/2022
  3119 00005490 58                  <1> 	pop	eax
  3120                              <1> ctty_stc_retn:	; 09/02/2022
  3121                              <1> ctty_4:
  3122 00005491 C3                  <1> 	retn
  3123                              <1> 
  3124                              <1> ;ctty_err: ; 13/01/2014
  3125                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3126                              <1> ;	jnz	error
  3127                              <1> ;	stc
  3128                              <1> ;	retn
  3129                              <1> 
  3130                              <1> 	; Original UNIX v1 'ctty' routine:
  3131                              <1> 	;	
  3132                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3133                              <1> 	;		;/ point r5 to the console tty buffer
  3134                              <1>         ;decb   (r5) / dec number of processes using console tty
  3135                              <1>         ;br     sret / return via sret
  3136                              <1> 
  3137                              <1> ;ccvt:	; < close tty >
  3138                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3139                              <1> 	;
  3140                              <1> 	; Retro UNIX 8086 v1 modification !
  3141                              <1> 	; 
  3142                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3143                              <1> 	;		(exactly different than this one)
  3144                              <1> 	;	was in 'u9.s' file.
  3145                              <1> 	;
  3146                              <1> 	; DL = 2 -> it is open for reading
  3147                              <1> 	; DL = 1 -> it is open for writing
  3148                              <1> 	;
  3149                              <1> 	; 17/09/2013
  3150                              <1> 	;sub 	al, 10
  3151                              <1> 	;cmp	al, 7
  3152                              <1> 	;jna	short cttyp
  3153                              <1> 	; 13/01/2014
  3154                              <1> 	;jmp	short cttyp
  3155                              <1> 
  3156                              <1> ;cppt: / close paper tape
  3157                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3158                              <1> ;1:
  3159                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3160                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3161                              <1> ;                          / and assign to free list
  3162                              <1> ;               br sret
  3163                              <1> ;        br     1b
  3164                              <1> 
  3165                              <1> ;ejec:	
  3166                              <1> ;	jmp	error
  3167                              <1> ;/ejec:
  3168                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3169                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3170                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3171                              <1> ;/       br     sret / return to caller via 'sret'
  3172                              <1> 
  3173                              <1> ejec:
  3174                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  3175                              <1> 	;	     - Printer Initialization
  3176                              <1> lpt_init:	
  3177                              <1> 	; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985
  3178                              <1> 	;
  3179                              <1> 	; Default printer port: 378h ; LPT1
  3180                              <1> 	
  3181 00005492 B401                <1>  	mov	ah, 1  ; INITIALIZE THE PRINTER PORT
  3182                              <1> 	;call	int17h
  3183 00005494 E8C3FAFFFF          <1> 	call	PRNOP
  3184 00005499 7414                <1> 	jz	short lpt_init_ok
  3185                              <1> 	
  3186                              <1> 	; replace error code with 'device not ready' error
  3187                              <1> 	; (this may be better for 'sysopen')
  3188 0000549B B80F000000          <1> 	mov	eax, ERR_PRN_NOT_RDY
  3189 000054A0 A3[ED680000]        <1> 	mov	[u.error], eax
  3190                              <1> 	;jmp	sysret ; (may be) ? ([u.r0] = file descriptor)
  3191 000054A5 A3[98680000]        <1> 	mov	[u.r0], eax
  3192 000054AA E963DEFFFF          <1> 	jmp	error ; (better)	
  3193                              <1> 	
  3194                              <1> lpt_init_ok:
  3195                              <1> 	;jmp	short cret
  3196 000054AF 58                  <1> 	pop	eax    ; inode number
  3197 000054B0 C3                  <1> 	retn
  3198                              <1> 	
  2112                                  %include 'u8.s'        ; 11/06/2015
  2113                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - SYS8.INC
  2114                              <1> ; Last Modification: 08/07/2022
  2115                              <1> ; ----------------------------------------------------------------------------
  2116                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2117                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2118                              <1> ;
  2119                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2120                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2121                              <1> ; <Bell Laboratories (17/3/1972)>
  2122                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2123                              <1> ;
  2124                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2125                              <1> ;
  2126                              <1> ; ****************************************************************************
  2127                              <1> 
  2128                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2129                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2130                              <1> ;; Word 1, byte 0 = device id
  2131                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2132                              <1> ;;          bit 9 = write bit
  2133                              <1> ;;	    bit 10 = read bit	  
  2134                              <1> ;;	    bit 12 = waiting to write bit	
  2135                              <1> ;;	    bit 13 = waiting to read bit
  2136                              <1> ;;	    bit 15 = inhibit bit
  2137                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2138                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2139                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2140                              <1> ;;
  2141                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2142                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2143                              <1> ;;
  2144                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2145                              <1> ;; Word 1, Byte 0 = device id
  2146                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2147                              <1> ;;          bit 9 = write bit
  2148                              <1> ;;	    bit 10 = read bit	  
  2149                              <1> ;;	    bit 12 = waiting to write bit	
  2150                              <1> ;;	    bit 13 = waiting to read bit
  2151                              <1> ;;	    bit 15 = inhibit bit
  2152                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2153                              <1> ;;
  2154                              <1> ;; Original UNIX v1 ->
  2155                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2156                              <1> ;; Original UNIX v1 -> 
  2157                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2158                              <1> ;;
  2159                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2160                              <1> ;;
  2161                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2162                              <1> ;;          0 = fd0
  2163                              <1> ;;	    1 = fd1
  2164                              <1> ;;	    2 = hd0
  2165                              <1> ;;	    3 = hd1
  2166                              <1> ;;	    4 = hd2
  2167                              <1> ;;	    5 = hd3
  2168                              <1> 
  2169                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2170                              <1> 
  2171                              <1> 	; 08/02/2022
  2172                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2173                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2174                              <1> 	; 26/04/2013
  2175                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2176                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2177                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2178                              <1> 
  2179                              <1> 	; 08/02/2022
  2180                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2181                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2182                              <1> 	; 26/04/2013
  2183                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2184                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2185                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2186                              <1> 
  2187                              <1> bread: 
  2188                              <1> 	; 08/02/2022
  2189                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2190                              <1> 	; 14/07/2015
  2191                              <1> 	; 10/07/2015
  2192                              <1> 	; 09/06/2015
  2193                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2194                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2195                              <1> 	;	
  2196                              <1> 	; / read a block from a block structured device
  2197                              <1> 	;
  2198                              <1> 	; INPUTS ->
  2199                              <1> 	;    [u.fofp] points to the block number
  2200                              <1> 	;    CX = maximum block number allowed on device
  2201                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2202                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2203                              <1> 	;    [u.count]	number of bytes to read in
  2204                              <1> 	; OUTPUTS ->
  2205                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2206                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2207                              <1> 	;
  2208                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2209                              <1> 	;
  2210                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2211                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2212                              <1> 	;	is increased by 1. For example: If user/program request 
  2213                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2214                              <1> 	;  	the next block number just as 512 byte reading is done.
  2215                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2216                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2217                              <1> 	;       enough to keep byte position/offset of the disk), this
  2218                              <1> 	;	defect will not be corrected, user/program must request
  2219                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2220                              <1> 	;       for achieving correct result. In future version(s), 
  2221                              <1> 	;	this defect will be corrected by using different 
  2222                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2223                              <1> 
  2224                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2225                              <1> 			       ; / (only works on tape)
  2226                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2227                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2228                              <1> ;1:
  2229                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2230                              <1> 			    ; / maximum block # allowed on device
  2231                              <1> 		; jnb short @f
  2232                              <1> 		; bhis	1f / yes, 1f (error)
  2233                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2234                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2235                              <1> 		; mov (sp)+,r1 / return block # to r1
  2236                              <1> 		; inc r1 / bump block # to next consecutive block
  2237                              <1> 		; dec (sp) / "2-1-cold" on stack
  2238                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2239                              <1> ;1:
  2240                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2241                              <1> 	;push	ecx ; **
  2242                              <1> 	; 26/04/2013
  2243                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2244 000054B1 2C03                <1> 	sub	al, 3
  2245                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2246 000054B3 A2[00690000]        <1> 	mov	[u.brwdev], al
  2247                              <1> 	; 09/06/2015
  2248                              <1> 	;movzx	ebx, al
  2249                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2250                              <1> 	; 12/01/2022 (BugFix)
  2251 000054B8 C0E002              <1> 	shl	al, 2 ; * 4
  2252 000054BB 8B88[FE5F0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2253                              <1> bread_0:
  2254 000054C1 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2255                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2256                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2257 000054C2 8B1D[A8680000]      <1> 	mov	ebx, [u.fofp]
  2258 000054C8 8B03                <1> 	mov	eax, [ebx]
  2259 000054CA C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2260                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2261                              <1> 			       ; / block #
  2262 000054CD 39C8                <1> 	cmp	eax, ecx
  2263                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2264                              <1>        	                     ; / block number allowed
  2265                              <1> 	;jnb	error 	     ; 18/04/2013
  2266                              <1> 		; bhis error10 / yes, error
  2267                              <1> 	; 08/02/2022
  2268                              <1> 	;jb	short bread_1
  2269                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2270                              <1> 	;jmp	error
  2271 000054CF 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2272                              <1> bread_1:
  2273                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2274                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2275                              <1> 	; eAX = Block number (zero based)
  2276                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2277                              <1> preread: ;; call preread
  2278 000054D1 BF[00690000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2279 000054D6 E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2280                              <1> 	;; jc 	error
  2281                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2282                              <1>         ; eAX = Block/Sector number (r1)
  2283                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2284                              <1> 	; 14/03/2013
  2285 000054DB 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2286                              <1>        		; br 1f / branch if block already in a I/O buffer
  2287 000054DD 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2288                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2289 000054E2 E8DA010000          <1> 	call	poke
  2290                              <1>         	; jsr r0,poke / perform the read
  2291                              <1> 	;;jc	error ;2 0/07/2013
  2292                              <1> ; 1:
  2293                              <1>  		; clr *$ps / ps = 0
  2294                              <1>         	; rts r0
  2295                              <1> 	; 08/02/2022
  2296 000054E7 7305                <1> 	jnc	short bread_2
  2297 000054E9 E937010000          <1> 	jmp	dskrd_err
  2298                              <1> 	;
  2299                              <1> ;; return from preread
  2300                              <1> bread_2:
  2301 000054EE 66810B0040          <1> 	or	word [ebx], 4000h 
  2302                              <1> 		; bis $40000,(r5) 
  2303                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2304                              <1> bread_3: ; 1:
  2305 000054F3 66F7030024          <1> 	test	word [ebx], 2400h
  2306                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2307 000054F8 7407                <1> 	jz	short bread_4
  2308                              <1> 		; beq 1f / no
  2309                              <1> 		; cmp cdev,$1 / disk or drum?
  2310                              <1> 		; ble 2f / yes
  2311                              <1> 		; tstb uquant / is the time quantum = 0?
  2312                              <1> 		; bne 2f / no, 2f
  2313                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2314                              <1> 		; jsr r0,sleep; 31. 
  2315                              <1> 			; / put process to sleep in channel 31 (tape)
  2316                              <1> 		; mov (sp)+,r5 / restore r5
  2317                              <1> 		; br 1b / go back
  2318                              <1> ; 2: / drum or disk
  2319                              <1>         ;; mov	cx, [s.wait_]+2 ;; 29/07/2013
  2320 000054FA E8C2F2FFFF          <1> 	call	idle
  2321                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2322 000054FF EBF2                <1> 	jmp	short bread_3
  2323                              <1>        		; br 1b
  2324                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2325 00005501 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2326                              <1> 		; bic $40000,(r5) / clear bit 14
  2327                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2328 00005506 83C308              <1> 	add	ebx, 8
  2329                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2330                              <1> 	; 09/06/2015
  2331 00005509 66833D[FD680000]00  <1> 	cmp	word [u.pcount], 0
  2332 00005511 7705                <1> 	ja	short bread_5
  2333 00005513 E880F8FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2334                              <1> bread_5:
  2335                              <1> 	; eBX = system (I/O) buffer address
  2336 00005518 E870000000          <1> 	call	dioreg
  2337                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2338                              <1> 	; esi = start address of the transfer (in the buffer)
  2339                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2340                              <1> 	; ecx = transfer count (in bytes)
  2341                              <1> 	;
  2342                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2343                              <1> ;   / of users data
  2344 0000551D F3A4                <1> 	rep	movsb
  2345                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2346                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2347                              <1>        		; bne 1b
  2348 0000551F 59                  <1> 	pop	ecx ; **
  2349 00005520 833D[BC680000]00    <1> 	cmp	dword [u.count], 0
  2350                              <1> 		; tst u.count / done
  2351 00005527 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2352                              <1>        		; beq 1f / yes, return
  2353                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2354                              <1>        		; br bread / read some more
  2355                              <1> ; 1:
  2356 00005529 58                  <1> 	pop	eax ; ****
  2357                              <1>        		; mov (sp)+,r0
  2358 0000552A C3                  <1>         retn		; 09/06/2015
  2359                              <1> 	;jmp	ret_ 
  2360                              <1> 		;jmp ret  / jump to routine that called readi
  2361                              <1> 
  2362                              <1> 	; 08/02/2022
  2363                              <1> brw_oov_err:
  2364 0000552B C705[ED680000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2364 00005533 0000                <1>
  2365 00005535 E9D8DDFFFF          <1> 	jmp	error
  2366                              <1> 
  2367                              <1> 	; 08/02/2022
  2368                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2369                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2370                              <1> 	; 26/04/2013
  2371                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2372                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2373                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2374                              <1> 
  2375                              <1> 
  2376                              <1> 	; 08/02/2022
  2377                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)				
  2378                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2379                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2380                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2381                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2382                              <1> 
  2383                              <1> bwrite:
  2384                              <1> 	; 08/02/2022
  2385                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2386                              <1> 	; 14/07/2015
  2387                              <1> 	; 10/07/2015
  2388                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2389                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2390                              <1> 	;	
  2391                              <1> 	;; / write on block structured device
  2392                              <1> 	;
  2393                              <1> 	; INPUTS ->
  2394                              <1> 	;    [u.fofp] points to the block number
  2395                              <1> 	;    CX = maximum block number allowed on device
  2396                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2397                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2398                              <1> 	;    [u.count]	number of bytes to user desires to write
  2399                              <1> 	; OUTPUTS ->
  2400                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2401                              <1> 	;
  2402                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2403                              <1> 	;
  2404                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2405                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2406                              <1> 	;	is increased by 1. For example: If user/program request 
  2407                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2408                              <1> 	;  	the next block number just as 512 byte writing is done.
  2409                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2410                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2411                              <1> 	;       enough to keep byte position/offset of the disk), this
  2412                              <1> 	;	defect will not be corrected, user/program must request
  2413                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2414                              <1> 	;       for achieving correct result. In future version(s), 
  2415                              <1> 	;	this defect will be corrected by using different 
  2416                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2417                              <1> 
  2418                              <1>        		; jsr r0,tstdeve / test the device for an error
  2419                              <1> 	;push	ecx ; **
  2420                              <1> 	; 26/04/2013
  2421                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2422 0000553A 2C03                <1> 	sub	al, 3
  2423                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2424 0000553C A2[00690000]        <1> 	mov	[u.brwdev], al
  2425                              <1> 	; 09/06/2015
  2426                              <1> 	;movzx	ebx, al
  2427                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2428                              <1> 	; 12/01/2022 (BugFix)
  2429 00005541 C0E002              <1> 	shl	al, 2 ; * 4
  2430 00005544 8B88[FE5F0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2431                              <1> bwrite_0:
  2432 0000554A 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2433                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2434                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2435 0000554B 8B1D[A8680000]      <1> 	mov	ebx, [u.fofp]
  2436 00005551 8B03                <1> 	mov	eax, [ebx]       
  2437 00005553 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2438                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2439 00005556 39C8                <1> 	cmp	eax, ecx
  2440                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2441                              <1>        	                     ; / block number allowed
  2442                              <1> 	;jnb	error	     ; 18/04/2013
  2443                              <1> 		; bhis error10 / yes, error
  2444                              <1>      	; 08/02/2022
  2445                              <1> 	;jb	short bwrite_1
  2446                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2447                              <1> 	;jmp	error
  2448 00005558 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2449                              <1> bwrite_1:
  2450                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2451                              <1> 		; inc *u.fofp / no, increment block number
  2452                              <1> 	; 09/06/2015 - 10/07/2015
  2453 0000555A 66833D[FD680000]00  <1> 	cmp	word [u.pcount], 0
  2454 00005562 7705                <1> 	ja	short bwrite_2
  2455 00005564 E82BF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2456                              <1> bwrite_2:
  2457 00005569 BF[00690000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2458 0000556E E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2459                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2460                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2461 00005573 E815000000          <1>         call	dioreg
  2462                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2463                              <1> 	; esi = destination address (in the buffer)
  2464                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2465                              <1> 	; ecx = transfer count (in bytes)
  2466                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2467 00005578 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2468 0000557A F3A4                <1> 	rep	movsb
  2469                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2470                              <1>        		; dec r3 / area to the I/O buffer
  2471                              <1>        		; bne 1b
  2472 0000557C E80D010000          <1> 	call	dskwr
  2473                              <1> 		; jsr r0,dskwr / write it out on the device
  2474 00005581 59                  <1> 	pop	ecx ; **
  2475 00005582 833D[BC680000]00    <1>         cmp     dword [u.count], 0
  2476                              <1> 		; tst u.count / done
  2477 00005589 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2478                              <1> 		; beq 1f / yes, 1f
  2479                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2480                              <1>        		; br bwrite / go back and write next block
  2481                              <1> ; 1:
  2482 0000558B 58                  <1> 	pop	eax ; ****
  2483                              <1>        		; mov (sp)+,r0
  2484 0000558C C3                  <1> 	retn		; 09/06/2015
  2485                              <1>         ;jmp	ret_ 
  2486                              <1> 		; jmp ret / return to routine that called writei
  2487                              <1> ;error10:
  2488                              <1> ;       jmp     error  ; / see 'error' routine
  2489                              <1> 
  2490                              <1> dioreg:
  2491                              <1> 	; 04/02/2022
  2492                              <1> 	; 14/07/2015
  2493                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2494                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2495                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2496                              <1> 	;	
  2497                              <1> 	; bookkeeping on block transfers of data
  2498                              <1> 	;
  2499                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2500                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2501                              <1> 	; 10/07/2015
  2502                              <1> 	; * returns byte offset from beginning of current sector buffer
  2503                              <1> 	; (beginning of data) in ESI
  2504                              <1> 	;
  2505 0000558D 8B0D[BC680000]      <1> 	mov	ecx, [u.count]
  2506                              <1> 		; mov u.count,r3 / move char count to r3
  2507                              <1> 	; 04/02/2022
  2508 00005593 31D2                <1> 	xor	edx, edx
  2509 00005595 B602                <1> 	mov	dh, 2
  2510                              <1> 	; edx = 512
  2511 00005597 39D1                <1> 	cmp	ecx, edx ; 512
  2512                              <1> 	;cmp 	ecx, 512
  2513                              <1> 		; cmp r3,$512. / more than 512. char?
  2514 00005599 7602                <1> 	jna	short dioreg_0
  2515                              <1> 		; blos 1f / no, branch
  2516 0000559B 89D1                <1> 	mov	ecx, edx ; 512
  2517                              <1> 	;mov	ecx, 512
  2518                              <1> 		; mov $512.,r3 / yes, just take 512.
  2519                              <1> dioreg_0:
  2520                              <1> 	; 09/06/2015
  2521 0000559D 663B0D[FD680000]    <1> 	cmp	cx, [u.pcount]
  2522 000055A4 7607                <1> 	jna	short dioreg_1
  2523 000055A6 668B0D[FD680000]    <1> 	mov	cx, [u.pcount]
  2524                              <1> dioreg_1:
  2525                              <1> ; 1:
  2526 000055AD 8B15[B8680000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2527                              <1> 	        ; mov u.base,r2 / put users base in r2
  2528 000055B3 010D[C0680000]      <1> 	add	[u.nread], ecx
  2529                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2530 000055B9 290D[BC680000]      <1> 	sub	[u.count], ecx
  2531                              <1> 		; sub r3,u.count / update count
  2532 000055BF 010D[B8680000]      <1> 	add	[u.base], ecx
  2533                              <1> 		; add r3,u.base / update base
  2534                              <1> 	; 10/07/2015
  2535                              <1> 	; Retro UNIX 386 v1 - modification !
  2536                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2537                              <1> 	; (It will point to next byte position instead of next block no.)
  2538 000055C5 8B35[A8680000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2539 000055CB 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2540 000055CD 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2541 000055CF 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2542 000055D4 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2543 000055D6 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2544                              <1> 	; 09/06/2015 - 10/07/2015
  2545 000055D8 66290D[FD680000]    <1> 	sub	[u.pcount], cx
  2546 000055DF 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2547 000055E5 8B3D[F9680000]      <1> 	mov	edi, [u.pbase]
  2548 000055EB 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2549 000055F1 01D7                <1> 	add	edi, edx
  2550 000055F3 893D[F9680000]      <1> 	mov	[u.pbase], edi
  2551 000055F9 010D[F9680000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2552 000055FF C3                  <1> 	retn
  2553                              <1> 		; rts r0 / return
  2554                              <1> 
  2555                              <1> dskrd:
  2556                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2557                              <1> 	; 18/08/2015
  2558                              <1> 	; 02/07/2015
  2559                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2560                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2561                              <1> 	;
  2562                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2563                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2564                              <1> 	; (number specified in r1) in the acquired buffer.)
  2565                              <1> 	; If the device is busy at the time dskrd is called,	
  2566                              <1> 	; dskrd calls idle.
  2567                              <1> 	; 
  2568                              <1> 	; INPUTS ->
  2569                              <1> 	;    r1 - block number
  2570                              <1> 	;    cdev - current device number 
  2571                              <1> 	; OUTPUTS ->
  2572                              <1> 	;    r5 - points to first data word in I/O buffer
  2573                              <1> 	;
  2574                              <1> 	; ((AX = R1)) input/output
  2575                              <1> 	; ((BX = R5)) output 
  2576                              <1> 	;
  2577                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2578                              <1> 	;
  2579 00005600 E851010000          <1> 	call 	bufaloc
  2580                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2581                              <1> 			       ; / get a free I/O buffer
  2582                              <1> 	;;jc	error ; 20/07/2013
  2583 00005605 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2584                              <1>        		; br 1f / branch if block already in a I/O buffer
  2585                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2586 00005607 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2587                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2588                              <1> 		               ; / I/O queue entry for buffer
  2589 0000560C E8B0000000          <1> 	call	poke
  2590                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2591                              <1> 			    ; /	bit 10=1 says read
  2592                              <1> 	; 09/06/2015
  2593                              <1> 	;jnc	short dskrd_1
  2594                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2595                              <1> 	;jmp	error
  2596                              <1> 	; 08/02/2022
  2597 00005611 7212                <1> 	jc	short dskrd_3
  2598                              <1> dskrd_1: ; 1:
  2599                              <1>        		;clr *$ps
  2600 00005613 66F7030024          <1>        	test	word [ebx], 2400h
  2601                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2602                              <1> 				; / jump to idle
  2603 00005618 7407                <1>        	jz	short dskrd_2
  2604                              <1> 		; beq 1f
  2605                              <1>         ;;mov   ecx, [s.wait_]
  2606 0000561A E8A2F1FFFF          <1>        	call	idle
  2607                              <1> 		; jsr r0,idle; s.wait+2
  2608 0000561F EBF2                <1> 	jmp 	short dskrd_1
  2609                              <1>        		; br 1b
  2610                              <1> dskrd_2: ; 1:
  2611 00005621 83C308              <1>         add	ebx, 8
  2612                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2613                              <1> 			  ; / just read in
  2614 00005624 C3                  <1>        	retn
  2615                              <1> 		; rts r0
  2616                              <1> dskrd_err: 
  2617                              <1> 	; 08/02/2022
  2618                              <1> 	; (jump from 'bread' error)	
  2619                              <1> dskrd_3:	
  2620                              <1> 	; 08/02/2022
  2621 00005625 803D[00690000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2622 0000562C 7509                <1> 	jne	short dskrd_4 ; no
  2623                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2624 0000562E C605[00690000]00    <1> 	mov	byte [u.brwdev], 0
  2625 00005635 EB0A                <1> 	jmp	short dskrd_5
  2626                              <1> dskrd_4:
  2627 00005637 C705[ED680000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2627 0000563F 0000                <1>
  2628                              <1> dskrd_5:
  2629 00005641 E9CCDCFFFF          <1> 	jmp	error
  2630                              <1> 
  2631                              <1> bwslot:
  2632                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2633                              <1> 	; 10/07/2015
  2634                              <1> 	;	If the block/sector is not placed in a buffer
  2635                              <1> 	;	before 'wslot', it must be read before
  2636                              <1> 	;	it is written! (Otherwise transfer counts less
  2637                              <1> 	;	than 512 bytes will be able to destroy existing 
  2638                              <1> 	;	data on disk.)
  2639                              <1> 	;
  2640                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2641                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2642                              <1> 	; Retro UNIX 8086 v1 modification !
  2643                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2644                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2645                              <1> 	;	-> eAX = block number
  2646                              <1> 	;
  2647 00005646 E818010000          <1> 	call	bufaloc_0
  2648 0000564B 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2649                              <1> 	; 12/01/2022
  2650                              <1> 	; ebx = buffer header address
  2651                              <1> bwslot_0:
  2652                              <1> 	; 10/07/2015
  2653 0000564D 8B35[A8680000]      <1> 	mov	esi, [u.fofp]
  2654 00005653 8B06                <1> 	mov	eax, [esi]
  2655 00005655 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2656 0000565A 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2657                              <1> 		       ; recent disk data must be placed in the buffer
  2658 0000565C 813D[BC680000]0002- <1> 	cmp	dword [u.count], 512
  2658 00005664 0000                <1>
  2659 00005666 730F                <1> 	jnb	short wslot_0	
  2660                              <1> bwslot_1:
  2661 00005668 E89AFFFFFF          <1> 	call	dskrd_0
  2662                              <1> 	; 12/01/2022
  2663                              <1> 	; ebx = buffer data address = buffer header address + 8
  2664 0000566D 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2665 00005670 EB05                <1> 	jmp 	short wslot_0
  2666                              <1> 
  2667                              <1> wslot:
  2668                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2669                              <1> 	; 		(32 bit modifications)
  2670                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2671                              <1> 	;
  2672                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2673                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2674                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2675                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2676                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2677                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2678                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2679                              <1> 	;
  2680                              <1> 	; INPUTS ->
  2681                              <1>  	;    r1 - block number
  2682                              <1> 	;    cdev - current (block/disk) device number
  2683                              <1>  	;
  2684                              <1> 	; OUTPUTS ->
  2685                              <1> 	;    bufp - bits 9 and 15 are set, 
  2686                              <1> 	;           the remainder of the word left unchanged
  2687                              <1> 	;    r5 - points to first data word in I/O buffer
  2688                              <1> 	;
  2689                              <1> 	; ((AX = R1)) input/output
  2690                              <1> 	; ((BX = R5)) output 
  2691                              <1> 	;
  2692                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2693                              <1> 
  2694 00005672 E8DF000000          <1> 	call	bufaloc
  2695                              <1> 	; 10/07/2015
  2696                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2697                              <1>         	; br 1f / word in buffer in r5
  2698                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2699                              <1>         ; eAX = Block/Sector number (r1)
  2700                              <1> wslot_0: ;1:
  2701 00005677 66F7030024          <1>      	test	word [ebx], 2400h
  2702                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2703                              <1> 				; / of I/O queue entry
  2704 0000567C 7407                <1> 	jz	short wslot_1
  2705                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2706                              <1> 		     ; / or not waiting to read)
  2707                              <1> 
  2708                              <1>         ;; mov     ecx, [s.wait_] ; 29/07/2013
  2709 0000567E E83EF1FFFF          <1> 	call	idle
  2710                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2711                              <1>        	                     ; / idle
  2712 00005683 EBF2                <1> 	jmp	short wslot_0
  2713                              <1> 		; br 1b / till finished
  2714                              <1> wslot_1: ;1:
  2715 00005685 66810B0082          <1>         or      word [ebx], 8200h
  2716                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2717                              <1>                             	 ; / (write, inhibit bits)
  2718                              <1>        		; clr     *$ps / clear processor status
  2719 0000568A 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2720                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2721                              <1> 			  ; / for this block
  2722                              <1> dskwr_1:	; 08/02/2022
  2723 0000568D C3                  <1>        	retn
  2724                              <1> 		; rts r0
  2725                              <1> dskwr:
  2726                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2727                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2728                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2729                              <1> 	;
  2730                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2731                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2732                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2733                              <1> 	; previously has supplied all the information required in the
  2734                              <1> 	; I/O queue entry.
  2735                              <1> 	;
  2736                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2737                              <1> 	;
  2738                              <1> 	;
  2739 0000568E 8B1D[58680000]      <1> 	mov	ebx, [bufp]
  2740 00005694 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2741                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2742                              <1>                                   ; / bottom of queue
  2743 00005699 E823000000          <1> 	call	poke
  2744                              <1> 	; 09/06/2015
  2745 0000569E 73ED                <1> 	jnc	short dskwr_1
  2746                              <1> 	; 08/02/2022
  2747 000056A0 803D[00690000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2748 000056A7 7509                <1> 	jne	short dskwr_0 ; no
  2749                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2750 000056A9 C605[00690000]00    <1> 	mov	byte [u.brwdev], 0
  2751 000056B0 EB0A                <1> 	jmp	short dskwr_2
  2752                              <1> dskwr_0:
  2753 000056B2 C705[ED680000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2753 000056BA 0000                <1>
  2754                              <1> dskwr_2:
  2755 000056BC E951DCFFFF          <1> 	jmp	error
  2756                              <1> ;dskwr_1:
  2757                              <1> ;	retn
  2758                              <1> 
  2759                              <1> ;ppoke:
  2760                              <1>        		; mov $340,*$ps
  2761                              <1>        		; jsr r0,poke
  2762                              <1>        		; clr *$ps
  2763                              <1> 		; rts r0
  2764                              <1> poke:
  2765                              <1> 	; 24/12/2021 (32 bit reg push-pop)
  2766                              <1> 	; 24/10/2015
  2767                              <1> 	; 20/08/2015
  2768                              <1> 	; 18/08/2015
  2769                              <1> 	; 02/07/2015
  2770                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2771                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2772                              <1> 	;
  2773                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2774                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2775                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2776                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2777                              <1> 	;
  2778                              <1> 	; Basic I/O functions for all block structured devices
  2779                              <1> 	;
  2780                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2781                              <1> 	;
  2782                              <1> 	; 20/07/2013 modifications
  2783                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2784                              <1> 	; INPUTS -> 
  2785                              <1> 	;        (EBX = buffer header address)
  2786                              <1> 	; OUTPUTS ->
  2787                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2788                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2789                              <1> 	;		(drive not ready or r/w error!)
  2790                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2791                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2792                              <1> 	;        (also it indicates invalid buffer data)
  2793                              <1> 	;
  2794 000056C1 53                  <1> 	push	ebx
  2795                              <1>        		; mov r1,-(sp)
  2796                              <1>        		; mov r2,-(sp)
  2797                              <1>        		; mov r3,-(sp)
  2798 000056C2 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2799                              <1> 	;
  2800                              <1> 	; 09/06/2015
  2801                              <1> 	; (permit read/write after a disk  R/W error)
  2802 000056C3 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2803 000056C5 B001                <1> 	mov	al, 1
  2804 000056C7 D2E0                <1> 	shl	al, cl
  2805 000056C9 8405[7E680000]      <1> 	test 	al, [active] ; busy ? (error)
  2806 000056CF 7408                <1> 	jz	short poke_0
  2807 000056D1 F6D0                <1> 	not	al
  2808 000056D3 2005[7E680000]      <1> 	and	[active], al ; reset busy bit for this device only
  2809                              <1> poke_0:
  2810 000056D9 BE[78680000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2811                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2812                              <1> 					 ; / I/O queue pointer
  2813                              <1> poke_1: ; 1:
  2814 000056DE 83EE04              <1>         sub	esi, 4
  2815 000056E1 8B1E                <1> 	mov	ebx, [esi]
  2816                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2817 000056E3 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2818 000056E6 F6C406              <1>        	test	ah, 06h
  2819                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2820                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2821                              <1> 			       ; / queue entry
  2822 000056E9 745C                <1>         jz      short poke_5
  2823                              <1> 		; beq 2f / branch to 2f if both are clear
  2824                              <1> 	; 31/07/2013
  2825                              <1> 	;test	ah, 0B0h ; (*)
  2826                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2827                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2828                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2829                              <1> 		; bne 2f / branch if any are set
  2830                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2831                              <1>     		; movb (r1),r3 / get device id
  2832 000056EB 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2833                              <1> 	;mov	edi, ecx ; 26/04/2013
  2834 000056EE 31C0                <1> 	xor 	eax, eax ; 0
  2835                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2836                              <1> 		; tstb deverr(r3) / test for errors on this device
  2837                              <1>        	;jna	short poke_2 
  2838                              <1> 		; beq 3f / branch if no errors
  2839                              <1> 	; 02/07/2015
  2840                              <1> 	;dec	eax
  2841                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2842                              <1>        		; mov $-1,2(r1) / destroy associativity
  2843                              <1> 	;shr	eax, 24
  2844                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2845                              <1> 		; clrb 1(r1) / do not do I/O
  2846                              <1> 	;jmp	short poke_5
  2847                              <1>         ;       ; br 2f
  2848                              <1>                 ; rts r0
  2849                              <1> poke_2: ; 3:
  2850                              <1> 	; 02/07/2015
  2851 000056F0 FEC1                <1> 	inc	cl ; 0FFh -> 0
  2852 000056F2 7453                <1> 	jz	short poke_5
  2853 000056F4 FEC0                <1> 	inc	al ; mov ax, 1
  2854 000056F6 FEC9                <1> 	dec	cl
  2855 000056F8 7402                <1> 	jz	short poke_3
  2856                              <1> 	; 26/04/2013 Modification
  2857                              <1> 	;inc	al ; mov ax, 1
  2858                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2859                              <1> 	;jz	short poke_3 ; cl = 0
  2860 000056FA D2E0                <1> 	shl	al, cl ; shl ax, cl
  2861                              <1> poke_3:
  2862                              <1> 	;test	[active], ax
  2863 000056FC 8405[7E680000]      <1> 	test	[active], al
  2864                              <1> 		; bit $2,active / test disk busy bit
  2865 00005702 7543                <1> 	jnz     short poke_5
  2866                              <1> 		; bne 2f / branch if bit is set
  2867                              <1> 	;or	[active], ax
  2868 00005704 0805[7E680000]      <1> 	or	[active], al
  2869                              <1> 		; bis $2,active / set disk busy bit
  2870                              <1> 	;push	ax
  2871                              <1> 	; 24/12/2021
  2872 0000570A 50                  <1> 	push	eax
  2873 0000570B E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2874                              <1> 	;mov    [edi+drv.error], ah
  2875                              <1> 	; 24/12/2021
  2876 00005710 58                  <1> 	pop	eax
  2877                              <1> 	;pop	ax
  2878 00005711 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2879                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2880                              <1> 	;jna	short poke_4
  2881                              <1> 		; tstb deverr(r3) / test for errors on this device
  2882                              <1>        		; beq 3f / branch if no errors
  2883                              <1> 	; 02/07/2015 (32 bit modification)
  2884                              <1> 	; 20/07/2013
  2885 00005713 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2886                              <1>        		; mov $-1,2(r1) / destroy associativity
  2887 0000571A 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2888                              <1> 		; clrb 1(r1) / do not do I/O
  2889 0000571F EB26                <1> 	jmp     short poke_5
  2890                              <1> poke_4:	; 20/07/2013
  2891                              <1> 	; 17/07/2013
  2892 00005721 F6D0                <1> 	not 	al 
  2893 00005723 2005[7E680000]      <1> 	and	[active], al ; reset, not busy
  2894                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2895                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2896 00005729 668B03              <1> 	mov	ax, [ebx]
  2897                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2898 0000572C 66250006            <1>         and	ax, 600h
  2899                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2900 00005730 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2901                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2902 00005735 C0E403              <1> 	shl	ah, 3
  2903                              <1>        		; rol r3
  2904                              <1>                 ; rol r3
  2905                              <1>                 ; rol r3	
  2906 00005738 660903              <1> 	or	[ebx], ax
  2907                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2908                              <1> 			   ; bits 12 and 13
  2909 0000573B E881F0FFFF          <1> 	call	idle ; 18/01/2014
  2910                              <1> 	;; sti
  2911                              <1> 	;hlt 	; wait for a hardware interrupt
  2912                              <1> 	;; cli
  2913                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2914                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2915                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2916                              <1> 	; method, this procedure will wait for a time according to
  2917                              <1> 	; multi tasking and time sharing concept.
  2918                              <1> 	;
  2919                              <1> 	; 24/10/2015
  2920                              <1> 	;not	ax 
  2921 00005740 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2922 00005744 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2923                              <1> poke_5: ;2:
  2924 00005747 81FE[58680000]      <1>         cmp     esi, bufp
  2925                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2926                              <1>                             ; / has been scanned
  2927 0000574D 778F                <1> 	ja      short poke_1
  2928                              <1>                ; bhi 1b
  2929                              <1> 	; 24/03/2013
  2930                              <1>        		; mov (sp)+,r3
  2931                              <1>        		; mov (sp)+,r2
  2932                              <1>        		; mov (sp)+,r1
  2933 0000574F 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2934 00005750 5B                  <1> 	pop 	ebx
  2935                              <1> 	; 02/07/2015 (32 bit modification)
  2936                              <1> 	; 20/07/2013
  2937                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2938 00005751 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2939                              <1> 	;	
  2940                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2941                              <1> 	; or written successfully; even if an error occurs while
  2942                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2943                              <1> 	;
  2944                              <1> 	; 09/06/2015
  2945 00005754 F5                  <1> 	cmc
  2946 00005755 C3                  <1> 	retn
  2947                              <1>                 ; rts r0
  2948                              <1> 
  2949                              <1> bufaloc:
  2950                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2951                              <1> 	; 20/08/2015
  2952                              <1> 	; 19/08/2015
  2953                              <1> 	; 02/07/2015
  2954                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2955                              <1> 	;	     (32 bit modifications)	
  2956                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2957                              <1> 	;
  2958                              <1> 	; bufaloc - Block device I/O buffer allocation
  2959                              <1> 	; 
  2960                              <1> 	; INPUTS ->
  2961                              <1> 	;    r1 - block number
  2962                              <1> 	;    cdev - current (block/disk) device number
  2963                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2964                              <1> 	; OUTPUTS ->
  2965                              <1> 	;    r5 - pointer to buffer allocated
  2966                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2967                              <1> 	;
  2968                              <1> 	; ((AX = R1)) input/output
  2969                              <1> 	; ((BX = R5)) output
  2970                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2971                              <1> 	;    zf=1 -> block already in a I/O buffer
  2972                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2973                              <1> 	;    ((DL = Device ID))
  2974                              <1> 	;    (((DH = 0 or 1)))
  2975                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2976                              <1> 	;    ((CX and DH will not be used after return)))
  2977                              <1> 
  2978                              <1> 	;;push 	esi ; ***
  2979                              <1> 		; mov r2,-(sp) / save r2 on stack
  2980                              <1>        		; mov $340,*$ps / set processor priority to 7
  2981                              <1> 	; 20/07/2013
  2982                              <1> 	; 26/04/2013
  2983                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2984                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  2985                              <1> 	;add	edi, ebx
  2986                              <1> 	; 09/01/2022
  2987 00005756 0FB63D[7B680000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2988 0000575D 81C7[7C680000]      <1> 	add	edi, rdev
  2989                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2990                              <1> 			;; eDI points to device id.
  2991 00005763 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2992                              <1> 	; 11/06/2015
  2993 00005766 80BB[1A600000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2994 0000576D 720F                <1> 	jb	short bufaloc_9
  2995 0000576F C705[ED680000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2995 00005777 0000                <1>
  2996 00005779 E994DBFFFF          <1> 	jmp	error
  2997                              <1> bufaloc_9:
  2998 0000577E 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2999                              <1> bufaloc_10: ; 02/07/2015
  3000 00005780 31ED                <1> 	xor 	ebp, ebp ; 0
  3001 00005782 55                  <1> 	push	ebp ; 0
  3002 00005783 89E5                <1>         mov     ebp, esp	
  3003                              <1> 	;
  3004                              <1> bufaloc_1: ;1:
  3005                              <1> 		; clr -(sp) / vacant buffer
  3006 00005785 BE[58680000]        <1>         mov 	esi, bufp
  3007                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3008                              <1> 			     ; / entrys in buffer area
  3009                              <1> bufaloc_2: ;2:
  3010 0000578A 8B1E                <1> 	mov	ebx, [esi]
  3011                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3012                              <1> 			    ; queue entry into r5
  3013 0000578C 66F70300F6          <1> 	test	word [ebx], 0F600h
  3014                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3015 00005791 7503                <1>         jnz	short bufaloc_3
  3016                              <1> 		; bne 3f / branch when 
  3017                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3018                              <1>                        ; / (i.e., buffer busy)
  3019 00005793 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  3020                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  3021                              <1> 			; / found points to word 2 of I/O queue entry)
  3022                              <1> bufaloc_3: ;3:
  3023                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3024                              <1> 	;
  3025 00005796 3813                <1> 	cmp	[ebx], dl	
  3026                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3027                              <1> 			       ; / as current device
  3028 00005798 7508                <1> 	jne	short bufaloc_4
  3029                              <1>        		; bne 3f
  3030 0000579A 394304              <1> 	cmp	[ebx+4], eax
  3031                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3032                              <1> 			     ; / same as current block number
  3033 0000579D 7503                <1>        	jne	short bufaloc_4
  3034                              <1> 		; bne 3f
  3035                              <1> 	;add	esp, 4
  3036 0000579F 59                  <1> 	pop	ecx
  3037                              <1>        		; tst (sp)+ / bump stack pointer
  3038 000057A0 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3039                              <1> 				; jump to bufaloc_6 in original Unix v1
  3040                              <1>        		; br 1f / use this buffer
  3041                              <1> bufaloc_4: ;3:
  3042 000057A2 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3043                              <1> 	;
  3044 000057A5 81FE[70680000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3045                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3046 000057AB 72DD                <1> 	jb	short bufaloc_2
  3047                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3048                              <1>                        ; / buffers not checked)
  3049 000057AD 5E                  <1>         pop	esi
  3050                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3051                              <1> 			     ; / to last free block
  3052 000057AE 09F6                <1>        	or	esi, esi 
  3053 000057B0 7507                <1> 	jnz	short bufaloc_5
  3054                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3055                              <1> 	        ; / if a free buffer is found branch to 2f
  3056                              <1>         ;; mov  ecx, [s.wait_]
  3057 000057B2 E80AF0FFFF          <1> 	call	idle
  3058                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  3059 000057B7 EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  3060                              <1>        		; br 1b
  3061                              <1> bufaloc_5: ;2:
  3062                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3063 000057B9 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3064                              <1> bufaloc_6: ;1:
  3065 000057BB 8B1E                <1>         mov    	ebx, [esi] 
  3066                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3067                              <1> 			     ; / entry in r5
  3068                              <1> 	;; 26/04/2013
  3069                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3070 000057BD 8813                <1> 	mov 	[ebx], dl
  3071                              <1> 		; movb cdev,(r5) / put current device number 
  3072                              <1> 				 ; / in I/O queue entry
  3073 000057BF 894304              <1> 	mov 	[ebx+4], eax
  3074                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3075                              <1> 			     ; / of I/O queue entry
  3076                              <1> bufaloc_7: ;1:
  3077 000057C2 81FE[58680000]      <1>         cmp	esi, bufp
  3078                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3079                              <1> 			     ; / and put latest assigned
  3080 000057C8 760A                <1> 	jna	short bufaloc_8	
  3081                              <1>        		; blos 1f / buffer on the top 
  3082                              <1> 			; / (this makes if the lowest priority)
  3083 000057CA 83EE04              <1> 	sub	esi, 4
  3084 000057CD 8B0E                <1> 	mov	ecx, [esi]
  3085 000057CF 894E04              <1> 	mov	[esi+4], ecx
  3086                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3087 000057D2 EBEE                <1> 	jmp 	short bufaloc_7        
  3088                              <1> 		; br 1b
  3089                              <1> bufaloc_8: ;1:
  3090 000057D4 891E                <1>         mov	[esi], ebx
  3091                              <1> 		; mov r5,(r2)
  3092                              <1> 	;;pop	esi ; ***
  3093                              <1>        		; mov (sp)+,r2 / restore r2
  3094 000057D6 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3095                              <1> 		; Retro UNIX 8086 v1 modification
  3096                              <1> 		; zf=1 --> block already is in an I/O buffer
  3097                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3098 000057D8 C3                  <1> 	retn
  3099                              <1> 		; rts r0
  3100                              <1> 
  3101                              <1> diskio:
  3102                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3103                              <1> 	;	((simplified and shortened 'diskio.s' code)
  3104                              <1> 	; 12/02/2022
  3105                              <1> 	; 10/02/2022
  3106                              <1> 	; 08/02/2022
  3107                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1 2022, Kernel v0.2.1.2)
  3108                              <1> 	; 10/07/2015
  3109                              <1> 	; 02/07/2015
  3110                              <1> 	; 16/06/2015
  3111                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3112                              <1> 	;	     (80386 protected mode modifications)	
  3113                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3114                              <1> 	;
  3115                              <1> 	; Retro UNIX 8086 v1 feature only !
  3116                              <1> 	;
  3117                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3118                              <1> 	; 04/07/2009 - 20/07/2011
  3119                              <1> 	;
  3120                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3121                              <1> 	;
  3122                              <1>         ; INPUTS ->
  3123                              <1> 	; 	   EBX = System I/O Buffer header address
  3124                              <1> 	;
  3125                              <1>         ; OUTPUTS -> cf=0 --> done 
  3126                              <1> 	; 	     cf=1 --> error code in AH
  3127                              <1> 	;	     ; 08/02/2022
  3128                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3129                              <1> 	;		error code in [u.error]
  3130                              <1> 	;		
  3131                              <1> 	; (Modified registers: EAX, ECX, EDX)
  3132                              <1> 	
  3133                              <1> ;rw_disk_sector:
  3134                              <1> 	; 08/07/2022
  3135                              <1> 	; 12/02/2022
  3136                              <1> 	; 10/02/2022
  3137                              <1> 	; 08/02/2022
  3138                              <1> 	; 10/07/2015
  3139                              <1> 	; 02/07/2015
  3140                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3141                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3142                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3143                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3144                              <1> 	;
  3145                              <1> 	;;mov	dx, 0201h ; Read 1 sector/block
  3146                              <1> 	;mov	dh, 2
  3147                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3148 000057D9 B602                <1> 	mov	dh, 2 ; Write 1 sector/block
  3149 000057DB 668B03              <1> 	mov	ax, [ebx] 
  3150                              <1> 	;
  3151 000057DE 56                  <1> 	push	esi ; ****
  3152 000057DF 53                  <1> 	push	ebx ; ***
  3153                              <1> 	;
  3154 000057E0 0FB6C8              <1> 	movzx	ecx, al
  3155 000057E3 89CE                <1> 	mov	esi, ecx
  3156                              <1> 	;
  3157 000057E5 38F1                <1> 	cmp	cl, dh ; 2
  3158 000057E7 7202                <1> 	jb	short rwdsk0
  3159 000057E9 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3160                              <1> rwdsk0:
  3161 000057EB A2[CB5F0000]        <1> 	mov	[drv], al
  3162 000057F0 81C6[1A600000]      <1> 	add	esi, drv.status
  3163                              <1> 	; 11/06/2015
  3164 000057F6 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3165 000057F9 7204                <1> 	jb      short rwdsk1
  3166                              <1> 	; 'drive not ready' error
  3167                              <1> 	; 10/02/2022
  3168                              <1> 	; 08/02/2022
  3169                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3170                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3171                              <1> 	;;jmp	error
  3172                              <1> 	;stc	; cf = 1
  3173                              <1> 	;retn
  3174                              <1> 	; 10/02/2022
  3175 000057FB B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3176 000057FD EB1F                <1> 	jmp	short rwdsk_err1
  3177                              <1> rwdsk1:
  3178                              <1> 	;test	ah, 2
  3179                              <1> 	;;test	ax, 200h ; Bit 9 of word 0 (status word)
  3180                              <1> 	;		 ; write bit
  3181                              <1> 	;jz	short rwdsk2
  3182                              <1> 	
  3183                              <1> 	;;test	ah, 4
  3184                              <1> 	;;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3185                              <1> 	;;		 ; read bit
  3186                              <1> 	;;jz	short diskio_ret
  3187                              <1> 
  3188                              <1> 	;inc	dh ; 03h = write
  3189                              <1> 
  3190                              <1> 	; 08/07/2022
  3191 000057FF 84F4                <1> 	test	ah, dh ; test ah, 2
  3192 00005801 7502                <1> 	jnz	short rwdsk2 ; dh = 02h = write
  3193 00005803 FECE                <1> 	dec	dh
  3194                              <1> 		; dh = 01h = read
  3195                              <1> rwdsk2:
  3196 00005805 88C2                <1> 	mov	dl, al
  3197 00005807 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3198 0000580A 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3199 0000580C C0E102              <1> 	shl	cl, 2
  3200 0000580F 81C1[FE5F0000]      <1> 	add	ecx, drv.size ; disk size
  3201 00005815 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3202 00005817 7214                <1> 	jb      short rwdsk3
  3203                              <1>  	; 'out of volume' error
  3204                              <1> 	; 10/02/2022
  3205                              <1> 	; 08/02/2022
  3206                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3207                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3208                              <1> 	;;jmp	error
  3209                              <1> 	;stc	; cf = 1
  3210                              <1> 	;retn
  3211                              <1> 	; 10/02/2022
  3212 00005819 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3213                              <1> rwdsk_err1:
  3214 0000581E C605[00690000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3215 00005825 890D[ED680000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3216 0000582B EB30                <1> 	jmp	short rwdsk_err2
  3217                              <1> rwdsk3:
  3218                              <1> 	; 11/06/2015
  3219 0000582D 83C304              <1> 	add	ebx, 4 ; buffer address
  3220 00005830 C605[1E690000]04    <1> 	mov	byte [retry_count], 4
  3221 00005837 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3222 0000583A 7432                <1>         jz      short rwdsk_chs
  3223                              <1> rwdsk_lba:
  3224                              <1> 	; LBA read/write (with private LBA function) 
  3225                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3226 0000583C 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3227 0000583F 89C1                <1> 	mov	ecx, eax ; sector number
  3228                              <1> 	; ebx = buffer (data) address
  3229                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3230                              <1> rwdsk_lba_retry:
  3231                              <1> 	;mov	dl, [drv]
  3232                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3233                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3234                              <1> 	;mov	ah, 1Ch - 03h ; LBA write function number - 3
  3235 00005841 B402                <1> 	mov	ah, 2 ; LBA write function number - 2
  3236 00005843 00F4                <1> 	add	ah, dh		
  3237 00005845 B001                <1> 	mov	al, 1
  3238                              <1> 	;int	13h
  3239 00005847 E83CC8FFFF          <1> 	call	int13h
  3240 0000584C 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3241 0000584E 730E                <1> 	jnc	short rwdsk_lba_ok
  3242 00005850 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3243 00005853 7408                <1>         je      short rwdsk_lba_fails
  3244 00005855 FE0D[1E690000]      <1> 	dec	byte [retry_count]
  3245 0000585B 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3246                              <1> rwdsk_err2:	; 10/02/2022
  3247                              <1> rwdsk_lba_fails:
  3248 0000585D F9                  <1> 	stc
  3249                              <1> rwdsk_lba_ok:
  3250 0000585E 5B                  <1> 	pop	ebx ; ***
  3251 0000585F 5E                  <1> 	pop	esi ; ****
  3252 00005860 C3                  <1> 	retn
  3253                              <1> rwdsk_lba_reset:
  3254                              <1> 	;mov	ah, 0Dh ; Alternate reset
  3255                              <1> 	;int	13h
  3256                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3257 00005861 B405                <1>         mov	ah, 5 ; Alternate reset	 
  3258 00005863 E820C8FFFF          <1> 	call	int13h
  3259 00005868 73D7                <1> 	jnc     short rwdsk_lba_retry
  3260 0000586A 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3261 0000586C EBF0                <1> 	jmp	short rwdsk_lba_ok
  3262                              <1> 	;
  3263                              <1> 	; CHS read (convert LBA address to CHS values)	
  3264                              <1> rwdsk_chs:
  3265                              <1> 	; 10/07/2015
  3266 0000586E 81EE[1A600000]      <1> 	sub	esi, drv.status
  3267 00005874 89F1                <1> 	mov	ecx, esi
  3268 00005876 81C6[21600000]      <1> 	add 	esi, drv.error
  3269                              <1> 	; 02/07/2015
  3270                              <1> 	; 16/06/2015
  3271                              <1>  	; 11/06/2015 
  3272 0000587C 53                  <1> 	push	ebx ; ** ; buffer
  3273 0000587D D1E1                <1> 	shl	ecx, 1
  3274 0000587F 51                  <1> 	push	ecx ; * 
  3275                              <1> 	;
  3276 00005880 89CB                <1> 	mov	ebx, ecx
  3277 00005882 8835[1D690000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3278 00005888 31D2                <1> 	xor	edx, edx ; 0
  3279                              <1> 	; 09/01/2022
  3280                              <1> 	;sub	ecx, ecx 
  3281 0000588A 81C3[F05F0000]      <1>         add     ebx, drv.spt
  3282 00005890 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3283                              <1> 		; EDX:EAX = LBA
  3284 00005893 F7F1                <1> 	div	ecx
  3285 00005895 88D1                <1> 	mov	cl, dl	; sector number - 1
  3286 00005897 FEC1                <1> 	inc	cl	; sector number (1 based)
  3287 00005899 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3288                              <1> 	;push	cx
  3289                              <1>         ; 09/01/2022
  3290 0000589A 51                  <1> 	push	ecx
  3291 0000589B 81C3[E25F0000]      <1> 	add     ebx, drv.heads
  3292 000058A1 668B0B              <1> 	mov	cx, [ebx] ; heads
  3293 000058A4 31D2                <1> 	xor	edx, edx
  3294                              <1> 		; EAX = cylinders * heads + head
  3295 000058A6 F7F1                <1> 	div	ecx
  3296                              <1> 	;pop	cx     ; sector number
  3297                              <1> 	; 09/01/2022
  3298 000058A8 59                  <1> 	pop	ecx
  3299 000058A9 88D6                <1> 	mov	dh, dl ; head number
  3300 000058AB 8A15[CB5F0000]      <1> 	mov	dl, [drv]
  3301 000058B1 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3302 000058B3 C0E406              <1> 	shl	ah, 6
  3303 000058B6 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3304                              <1> 		       ; sector (bits 0-7)
  3305 000058B8 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3306                              <1> 		; CL = sector (bits 0-5)
  3307                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3308                              <1> 		; CH = cylinder (bits 0-7)
  3309                              <1> 		; DH = head
  3310                              <1> 		; DL = drive
  3311                              <1> 	;
  3312 000058B9 C605[1E690000]04    <1> 	mov	byte [retry_count], 4
  3313                              <1> rwdsk_retry:	
  3314                              <1> 	;mov	ah, [rwdsk] ; 02h = read, 03h = write
  3315                              <1> 	; 08/07/2022
  3316 000058C0 8A25[1D690000]      <1> 	mov	ah, [rwdsk] ; 01h = read, 02h = write
  3317 000058C6 B001                <1> 	mov	al, 1 ; sector count	
  3318                              <1> 	;int	13h
  3319                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3320 000058C8 E8BBC7FFFF          <1> 	call	int13h
  3321 000058CD 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3322 000058CF 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3323 000058D1 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3324 000058D4 7408                <1> 	je	short rwdsk_fails
  3325 000058D6 FE0D[1E690000]      <1> 	dec	byte [retry_count]
  3326 000058DC 7504                <1> 	jnz	short rwdsk_reset
  3327                              <1> rwdsk_fails:
  3328 000058DE F9                  <1> 	stc
  3329                              <1> rwdsk_ok:
  3330 000058DF 5B                  <1> 	pop	ebx ; ***
  3331 000058E0 5E                  <1> 	pop	esi ; ****
  3332 000058E1 C3                  <1> 	retn
  3333                              <1> rwdsk_reset:
  3334                              <1> 	; 02/02/2015
  3335 000058E2 28E4                <1> 	sub	ah, ah
  3336 000058E4 80FA80              <1> 	cmp	dl, 80h
  3337 000058E7 7202                <1> 	jb	short rwdsk_fd_reset
  3338                              <1> 	;mov	ah, 0Dh ; Alternate reset
  3339                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3340 000058E9 B405                <1> 	mov	ah, 5  ; Alternate reset
  3341                              <1> rwdsk_fd_reset:
  3342                              <1> 	;int	13h
  3343 000058EB E898C7FFFF          <1>         call	int13h
  3344 000058F0 73CE                <1> 	jnc	short rwdsk_retry
  3345 000058F2 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3346 000058F4 EBE9                <1> 	jmp 	short rwdsk_ok
  3347                              <1> 
  3348                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3349                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3350                              <1> ;
  3351                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3352                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3353                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3354                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3355                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3356                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3357                              <1> ; as in original unix v1.
  3358                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3359                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3360                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3361                              <1> ;
  3362                              <1> ; Erdogan tan (10/07/2015) 
  3363                              <1> 
  3364                              <1> ;drum: / interrupt handler
  3365                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3366                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3367                              <1> ;                                      / error
  3368                              <1> ;               br 3f / no, error
  3369                              <1> ;       br      2f / error
  3370                              <1> ;
  3371                              <1> ;disk:
  3372                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3373                              <1> ;       jmp     *$0f
  3374                              <1> ;0:
  3375                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3376                              <1> ;      	        br 3f / no, errors
  3377                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3378                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3379                              <1> ;                        / to 1f
  3380                              <1> ;       br      4f
  3381                              <1> ;1:
  3382                              <1> ;       bit     $20000,rkcs
  3383                              <1> ;       beq     4f / wait for seek complete
  3384                              <1> ;       mov     $0b,0b-2
  3385                              <1> ;       mov     rkap,r1
  3386                              <1> ;2:
  3387                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3388                              <1> ;                          / the disk buffer
  3389                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3390                              <1> ;       inc     r1
  3391                              <1> ;       asr     (r1)
  3392                              <1> ;       asr     (r1)
  3393                              <1> ;       asr     (r1) / reissue request
  3394                              <1> ;       dec     r1
  3395                              <1> ;3:
  3396                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3397                              <1> ;       mov     ac,-(sp)
  3398                              <1> ;       mov     mq,-(sp) / put these on the stack
  3399                              <1> ;       mov     sc,-(sp)
  3400                              <1> ;       jsr     r0,poke
  3401                              <1> ;       mov     (sp)+,sc
  3402                              <1> ;       mov     (sp)+,mq / pop them off stack
  3403                              <1> ;       mov     (sp)+,ac
  3404                              <1> ;4:
  3405                              <1> ;       jmp     retisp / u4-3
  3406                              <1> ;
  3407                              <1> ;trapt:                  / r2 points to the
  3408                              <1> ;       mov     (r0)+,r2 / device control register
  3409                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3410                              <1> ;       tst     (sp)+
  3411                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3412                              <1> ;       bge     4b / device still active so branch
  3413                              <1> ;       bit     (r0),active / was device busy?
  3414                              <1> ;       beq     4b / no, stray interrupt
  3415                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3416                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3417                              <1> ;       bge     2f / if no error jump to 2f
  3418                              <1> ;       tst     (r0)+ / skip on error
  3419                              <1> ; 2:
  3420                              <1> ;       jmp     (r0)
  2113                                  %include 'u9.s'        ; 29/06/2015
  2114                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS9.INC
  2115                              <1> ; Last Modification: 13/06/2022
  2116                              <1> ; ----------------------------------------------------------------------------
  2117                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2118                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2119                              <1> ;
  2120                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2121                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2122                              <1> ; <Bell Laboratories (17/3/1972)>
  2123                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2124                              <1> ;
  2125                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2126                              <1> ;
  2127                              <1> ; ****************************************************************************
  2128                              <1> 
  2129                              <1> getch:
  2130                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2131                              <1> 	; 30/06/2015
  2132                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2133 000058F6 28C0                <1> 	sub	al, al ; 0
  2134                              <1> getch_q: ; 06/08/2015
  2135 000058F8 8A25[06650000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2136 000058FE EB06                <1>         jmp     short getc_n
  2137                              <1> 
  2138                              <1> getc: 
  2139                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2140                              <1> 	; 12/11/2015
  2141                              <1> 	; 15/09/2015
  2142                              <1> 	; 01/07/2015
  2143                              <1> 	; 30/06/2015
  2144                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2145                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2146                              <1> 	;
  2147                              <1> 	; Retro UNIX 8086 v1 modification !
  2148                              <1> 	; 
  2149                              <1> 	; 'getc' gets (next) character 
  2150                              <1> 	;	 from requested TTY (keyboard) buffer 
  2151                              <1> 	; INPUTS ->
  2152                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2153                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2154                              <1> 	;	(Keyboard buffer will point to 
  2155                              <1> 	;			next character at next call)
  2156                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2157                              <1> 	;	(Keyboard buffer will point to 
  2158                              <1> 	;			current character at next call)
  2159                              <1> 	; OUTPUTS ->
  2160                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2161                              <1> 	;     			 ZF=0 -> AX has (current) character
  2162                              <1> 	;      AL = ascii code
  2163                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2164                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2165                              <1> 	; Original UNIX V1 'getc': 
  2166                              <1> 	;		get a character off character list
  2167                              <1> 	;
  2168                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2169                              <1> 	;
  2170                              <1> 	; 30/06/2015 (32 bit modifications)
  2171                              <1> 	; 16/07/2013
  2172                              <1> 	; mov 	[getctty], ah
  2173                              <1> 	;
  2174                              <1> 
  2175 00005900 8A25[EC680000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2176                              <1> getc_n:
  2177                              <1> 	; 30/06/2015
  2178 00005906 08E4                <1> 	or	ah, ah
  2179 00005908 740D                <1> 	jz	short getc0 
  2180 0000590A D0E4                <1> 	shl	ah, 1
  2181 0000590C 0FB6DC              <1> 	movzx	ebx, ah
  2182 0000590F 81C3[08650000]      <1> 	add	ebx, ttychr
  2183 00005915 EB05                <1> 	jmp	short getc1
  2184                              <1> getc0:
  2185 00005917 BB[08650000]        <1> 	mov	ebx, ttychr
  2186                              <1> getc1:
  2187 0000591C 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2188                              <1> 				; (by kb_int)	
  2189 0000591F 6609C9              <1> 	or	cx, cx
  2190 00005922 7507                <1> 	jnz	short getc2
  2191 00005924 20C0                <1> 	and 	al, al
  2192 00005926 7415                <1> 	jz	short getc_s
  2193                              <1> 	;xor	ax, ax
  2194                              <1> 	; 24/12/2021
  2195 00005928 31C0                <1> 	xor	eax, eax
  2196 0000592A C3                  <1> 	retn
  2197                              <1> getc2:	
  2198 0000592B 20C0                <1> 	and	al, al
  2199 0000592D 6689C8              <1> 	mov	ax, cx
  2200 00005930 66B90000            <1> 	mov	cx, 0
  2201 00005934 7506                <1> 	jnz	short getc3
  2202                              <1> getc_sn:
  2203 00005936 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2204 00005939 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2205                              <1> getc3:
  2206 0000593C C3                  <1> 	retn
  2207                              <1> getc_s:
  2208                              <1> 	; 12/11/2015
  2209                              <1> 	; 15/09/2015
  2210                              <1> 	; 01/07/2015
  2211                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2212                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2213                              <1> 	;
  2214                              <1> 	; tty  of the current process is not 
  2215                              <1> 	; current tty (ptty); so, current process only 
  2216                              <1> 	; can use keyboard input when its tty becomes 
  2217                              <1> 	; current tty (ptty).
  2218                              <1> 	; 'sleep' is for preventing an endless lock
  2219                              <1> 	; during this tty input request.
  2220                              <1> 	; (Because, the user is not looking at the video page
  2221                              <1> 	; of the process to undersand there is a keyboard
  2222                              <1> 	; input request.)
  2223                              <1> 	;
  2224                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2225                              <1> 	;
  2226                              <1> 	; 05/10/2013
  2227                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2228                              <1> 	;
  2229                              <1> 	; 10/10/2013
  2230                              <1> gcw0:
  2231 0000593D B10A                <1> 	mov	cl, 10 ; ch = 0
  2232                              <1> gcw1:	
  2233                              <1> 	; 12/11/2015
  2234 0000593F E8DBDAFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2235                              <1> 	; 10/10/2013
  2236 00005944 E878EEFFFF          <1> 	call	idle
  2237 00005949 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2238                              <1> 				; (by kb_int)
  2239 0000594C 6609C0              <1> 	or	ax, ax
  2240                              <1> ;	jnz	short gcw3
  2241 0000594F 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2242                              <1> 	; 30/06/2015
  2243 00005951 FEC9                <1> 	dec	cl
  2244 00005953 75EA                <1> 	jnz	short gcw1
  2245                              <1> 	;
  2246 00005955 8A25[EC680000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2247                              <1> ;	; 10/12/2013
  2248                              <1> ;	cmp 	ah, [ptty]
  2249                              <1> ;	jne	short gcw2
  2250                              <1> ;	; 14/02/2014
  2251                              <1> ;	cmp	byte [u.uno], 1
  2252                              <1> ;	jna	short gcw0		
  2253                              <1> ;gcw2:
  2254 0000595B E8EEEEFFFF          <1> 	call	sleep
  2255                              <1> 	;
  2256                              <1> 	; 20/09/2013
  2257 00005960 8A25[EC680000]      <1> 	mov	ah, [u.ttyn]
  2258 00005966 30C0                <1> 	xor 	al, al
  2259 00005968 EB9C                <1> 	jmp	short getc_n
  2260                              <1> ;gcw3:
  2261                              <1> gcw2: 	; 15/09/2015
  2262                              <1> 	; 10/10/2013
  2263 0000596A 30C9                <1> 	xor	cl, cl
  2264 0000596C EBC8                <1> 	jmp	short getc_sn
  2265                              <1> 
  2266                              <1> putc:	
  2267                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2268                              <1> 	; 13/08/2015
  2269                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2270                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2271                              <1> 	;
  2272                              <1> 	; Retro UNIX 8086 v1 modification !
  2273                              <1> 	; 
  2274                              <1> 	; 'putc' puts a character 
  2275                              <1> 	;	 onto requested (tty) video page or
  2276                              <1> 	;	 serial port
  2277                              <1> 	; INPUTS ->
  2278                              <1> 	;     AL = ascii code of the character
  2279                              <1> 	;     AH = video page (tty) number (0 to 7)
  2280                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2281                              <1> 	; OUTPUTS ->
  2282                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2283                              <1> 	;      			ZF=0 -> AX has (current) character
  2284                              <1> 	;     cf=0 and AH = 0 -> no error
  2285                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2286                              <1> 	; 
  2287                              <1> 	; Original UNIX V1 'putc': 
  2288                              <1> 	;     put a character at the end of character list
  2289                              <1> 	;
  2290                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2291                              <1> 	;
  2292 0000596E 80FC07              <1> 	cmp	ah, 7
  2293                              <1>         ;ja	sndc
  2294 00005971 770A                <1>         ja      short sndc ; 24/12/2024
  2295                              <1> 	; 30/06/2015
  2296 00005973 0FB6DC              <1> 	movzx	ebx, ah
  2297                              <1> 	; 13/08/2015
  2298 00005976 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2299 00005978 E944BAFFFF          <1> 	jmp	write_tty ; 'video.inc'
  2300                              <1> 
  2301                              <1> sndc:   ; <Send character>
  2302                              <1> 	;
  2303                              <1> 	; 12/01/2022
  2304                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2305                              <1> 	; 17/11/2015
  2306                              <1> 	; 16/11/2015
  2307                              <1> 	; 11/11/2015
  2308                              <1> 	; 10/11/2015
  2309                              <1> 	; 09/11/2015
  2310                              <1> 	; 08/11/2015
  2311                              <1> 	; 07/11/2015
  2312                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2313                              <1> 	; 29/10/2015
  2314                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2315                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2316                              <1> 	;
  2317                              <1> 	; Retro UNIX 8086 v1 feature only !
  2318                              <1> 	;
  2319                              <1> 	; ah = [u.ttyn]
  2320                              <1> 	;
  2321                              <1> 	; 30/06/2015
  2322 0000597D 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2323                              <1> 	; 07/11/2015
  2324 00005980 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2325                              <1> sndc0:
  2326                              <1> 	; 07/11/2015
  2327 00005983 E814EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2328 00005988 7405                <1> 	jz	short sndc1
  2329 0000598A E890DAFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2330                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2331                              <1> sndc1:
  2332                              <1> 	; 16/11/2015
  2333                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2334                              <1> 	; 24/12/2021
  2335 0000598F 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2336                              <1> sndcx:
  2337 00005991 8A83[4A650000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2338 00005997 8AA3[48650000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2339                              <1> 	;
  2340                              <1> 	; 17/11/2015
  2341                              <1> 	; check 'request for response' status
  2342 0000599D 80BB[44650000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2343 000059A4 740A                <1> 	jz	short query
  2344                              <1> response:
  2345 000059A6 FE05[47650000]      <1> 	inc 	byte [comqr] ; query or response status
  2346 000059AC B0FF                <1> 	mov	al, 0FFh	 
  2347 000059AE EB14                <1> 	jmp	short sndc3
  2348                              <1> query:
  2349 000059B0 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2350 000059B2 750E                <1> 	jnz 	short sndc2 ; normal character
  2351                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2352                              <1> 	;je	short sndc2  ; yes, already responded
  2353                              <1> 	; 16/11/2015
  2354                              <1> 	; query: request for response (again)
  2355 000059B4 8883[48650000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2356 000059BA FE05[47650000]      <1> 	inc 	byte [comqr] ; query or response status
  2357 000059C0 EB02                <1> 	jmp	short sndc3
  2358                              <1> sndc2:
  2359 000059C2 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2360                              <1> sndc3:
  2361 000059C4 8883[4A650000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2362 000059CA 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2363                              <1> 	; 30/06/2015
  2364 000059CC E8F4D3FFFF          <1> 	call	sp_status ; get serial port status
  2365                              <1> 	; AL = Line status, AH = Modem status
  2366                              <1> 	; 07/11/2015
  2367 000059D1 A880                <1> 	test	al, 80h
  2368 000059D3 7504                <1> 	jnz	short sndc4
  2369 000059D5 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2370 000059D7 751A                <1> 	jnz	short sndc5
  2371                              <1> sndc4: 	; Check line status again
  2372                              <1> 	; 16/11/2015
  2373                              <1> 	;push	cx
  2374                              <1> 	; 24/12/2021
  2375 000059D9 51                  <1> 	push	ecx
  2376                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2377                              <1> 	; 12/01/2022
  2378 000059DA 31C9                <1> 	xor	ecx, ecx
  2379 000059DC B106                <1> 	mov	cl, 6
  2380 000059DE E8D5BAFFFF          <1> 	call	WAITF
  2381                              <1> 	;pop	cx
  2382                              <1> 	; 24/12/1021
  2383 000059E3 59                  <1> 	pop	ecx
  2384                              <1> 	;
  2385 000059E4 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2386 000059E6 E8DAD3FFFF          <1> 	call	sp_status ; get serial port status
  2387                              <1> 	; 16/11/2015
  2388                              <1> 	; 09/11/2015
  2389                              <1> 	; 08/11/2015
  2390 000059EB A880                <1> 	test	al, 80h	; time out error
  2391 000059ED 7565                <1>         jnz     short sndc7
  2392 000059EF A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2393 000059F1 7461                <1>         jz	short sndc7
  2394                              <1> sndc5:  
  2395 000059F3 8A83[4A650000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2396 000059F9 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2397 000059FD 28DE                <1> 	sub	dh, bl
  2398 000059FF EE                  <1> 	out	dx, al	   ; send on serial port
  2399                              <1> 	; 10/11/2015
  2400                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2401                              <1> 	; (to improve text flow to the terminal)
  2402                              <1> 	; ('diskette.inc': 'WAITF')
  2403                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2404                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2405                              <1> 	;push	cx
  2406                              <1> 	; 24/12/2021
  2407 00005A00 51                  <1> 	push	ecx
  2408                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2409                              <1> 	; 12/01/2022
  2410 00005A01 29C9                <1> 	sub	ecx, ecx
  2411 00005A03 B106                <1> 	mov	cl, 6
  2412 00005A05 E8AEBAFFFF          <1> 	call	WAITF
  2413                              <1> 	;pop	cx
  2414                              <1> 	; 24/12/1021
  2415 00005A0A 59                  <1> 	pop	ecx
  2416                              <1>     	;
  2417                              <1> 	; 07/11/2015
  2418 00005A0B 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2419                              <1> 	;
  2420 00005A0D E8B3D3FFFF          <1> 	call	sp_status ; get serial port status
  2421                              <1> 	; AL = Line status, AH = Modem status
  2422                              <1> 	;
  2423 00005A12 E885EEFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2424 00005A17 7405                <1> 	jz	short sndc6
  2425 00005A19 E801DAFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2426                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2427                              <1> sndc6:
  2428 00005A1E 3C80                <1> 	cmp	al, 80h
  2429 00005A20 7332                <1> 	jnb	short sndc7		
  2430                              <1> 	;
  2431 00005A22 803D[47650000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2432 00005A29 7244                <1> 	jb	short sndc8 	; no, normal character
  2433 00005A2B 883D[47650000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2434                              <1> 	; 17/11/2015
  2435 00005A31 E88BEDFFFF          <1> 	call	idle
  2436                              <1> 	;
  2437 00005A36 38BB[4A650000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2438                              <1>         ;ja	sndc2       ; response (will be followed by
  2439                              <1> 			    ; a normal character)
  2440                              <1> 	; 24/12/2021
  2441 00005A3C 7602                <1> 	jna	short sndc_10
  2442 00005A3E EB82                <1> 	jmp	sndc2
  2443                              <1> sndc_10:
  2444                              <1> 	; Query request must be responded by the terminal
  2445                              <1> 	; before sending a normal character !
  2446 00005A40 53                  <1> 	push	ebx
  2447                              <1> 	;push	cx ; *** cl = character (to be sent)
  2448                              <1> 	; 24/12/2021
  2449 00005A41 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2450 00005A42 8A25[EC680000]      <1> 	mov	ah, [u.ttyn]
  2451 00005A48 E801EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2452                              <1> 		      ; received data available interrupt
  2453                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2454                              <1> 	; 24/12/2021
  2455 00005A4D 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2456 00005A4E 5B                  <1> 	pop	ebx
  2457 00005A4F E93DFFFFFF          <1>         jmp	sndcx
  2458                              <1> sndc7:
  2459                              <1> 	 ; 16/11/2015
  2460 00005A54 803D[47650000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2461 00005A5B 7213                <1> 	jb	short sndc9 	; no
  2462                              <1> 	;
  2463 00005A5D 88BB[48650000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2464 00005A63 88BB[4A650000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2465                              <1> 	;
  2466 00005A69 883D[47650000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2467                              <1> sndc8:
  2468 00005A6F F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2469                              <1> sndc9:
  2470                              <1> 	; AL = Line status, AH = Modem status
  2471 00005A70 C3                  <1> 	retn
  2472                              <1> 
  2473                              <1> get_cpos:
  2474                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2475                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2476                              <1> 	;
  2477                              <1> 	; INPUT -> bl = video page number
  2478                              <1> 	; RETURN -> dx = cursor position
  2479                              <1> 
  2480 00005A71 53                  <1> 	push	ebx
  2481 00005A72 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2482 00005A75 D0E3                <1> 	shl	bl, 1
  2483 00005A77 81C3[F6640000]      <1> 	add	ebx, cursor_posn
  2484 00005A7D 668B13              <1> 	mov	dx, [ebx]
  2485 00005A80 5B                  <1> 	pop	ebx
  2486 00005A81 C3                  <1> 	retn
  2487                              <1> 
  2488                              <1> read_ac_current:
  2489                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2490                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2491                              <1> 	;
  2492                              <1> 	; INPUT -> bl = video page number
  2493                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2494                              <1> 
  2495 00005A82 E8A0BAFFFF          <1> 	call 	find_position ; 'video.inc'
  2496                              <1> 	; dx = status port
  2497                              <1> 	; esi = cursor location/address
  2498 00005A87 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2499 00005A8D 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2500 00005A90 C3                  <1> 	retn
  2501                              <1> 
  2502                              <1> syssleep:
  2503                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2504                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2505                              <1> 	;
  2506                              <1> 	; Retro UNIX 8086 v1 feature only
  2507                              <1> 	; (INPUT -> none)
  2508                              <1> 	;
  2509 00005A91 0FB61D[E7680000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2510 00005A98 8AA3[F3650000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2511 00005A9E E8ABEDFFFF          <1> 	call	sleep
  2512 00005AA3 E98AD8FFFF          <1> 	jmp	sysret
  2513                              <1> 
  2514                              <1> 	; 27/02/2022
  2515                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2516                              <1> %if 0
  2517                              <1> 
  2518                              <1> vp_clr:
  2519                              <1> 	; Reset/Clear Video Page
  2520                              <1> 	;
  2521                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2522                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2523                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2524                              <1> 	;
  2525                              <1> 	; Retro UNIX 8086 v1 feature only !
  2526                              <1> 	;
  2527                              <1> 	; INPUTS -> 
  2528                              <1> 	;   BL = video page number	 
  2529                              <1> 	;
  2530                              <1> 	; OUTPUT ->
  2531                              <1> 	;   none
  2532                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2533                              <1> 	;
  2534                              <1> 	; 04/12/2013
  2535                              <1> 	sub	al, al
  2536                              <1> 	; al = 0 (clear video page)
  2537                              <1> 	; bl = video page
  2538                              <1> 	mov	ah, 07h
  2539                              <1> 	; ah = 7 (attribute/color)
  2540                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2541                              <1> 	; 24/12/2021
  2542                              <1> 	xor	ecx, ecx
  2543                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2544                              <1> 	call	scroll_up
  2545                              <1> 	; bl = video page
  2546                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2547                              <1> 	; 24/12/2021
  2548                              <1> 	xor	edx, edx 
  2549                              <1> 	jmp 	set_cpos
  2550                              <1> 
  2551                              <1> %endif
  2552                              <1> 
  2553                              <1> sysmsg:
  2554                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2555                              <1> 	; 11/11/2015
  2556                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2557                              <1> 	; Print user-application message on user's console tty
  2558                              <1> 	;
  2559                              <1> 	; Input -> EBX = Message address
  2560                              <1> 	;	   ECX = Message length (max. 255)
  2561                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2562                              <1> 	;
  2563 00005AA8 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2564                              <1> 	;ja	sysret ; nothing to do with big message size
  2565 00005AAE 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2566 00005AB0 08C9                <1> 	or	cl, cl
  2567                              <1> 	;jz	sysret
  2568 00005AB2 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2569 00005AB4 20D2                <1> 	and	dl, dl
  2570 00005AB6 7502                <1> 	jnz	short sysmsg0
  2571 00005AB8 B207                <1> 	mov	dl, 07h ; default color
  2572                              <1> 		; (black background, light gray character)
  2573                              <1> sysmsg0:
  2574 00005ABA 891D[B8680000]      <1> 	mov	[u.base], ebx
  2575 00005AC0 8815[07650000]      <1> 	mov	[ccolor], dl ; color attributes
  2576 00005AC6 89E5                <1> 	mov	ebp, esp
  2577 00005AC8 31DB                <1> 	xor	ebx, ebx ; 0
  2578 00005ACA 891D[C0680000]      <1> 	mov	[u.nread], ebx ; 0
  2579                              <1> 	;
  2580 00005AD0 381D[FF680000]      <1> 	cmp	[u.kcall], bl ; 0
  2581 00005AD6 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2582                              <1> 	;
  2583 00005AD8 890D[BC680000]      <1> 	mov	[u.count], ecx
  2584 00005ADE 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2585                              <1> 	; 24/12/2021
  2586                              <1> 	; (dword alignment for esp)
  2587 00005ADF F6C103              <1> 	test	cl, 3
  2588 00005AE2 7404                <1> 	jz	short sysmsg_7
  2589 00005AE4 80C903              <1> 	or	cl, 3
  2590 00005AE7 41                  <1> 	inc	ecx
  2591                              <1> sysmsg_7:
  2592 00005AE8 29CC                <1> 	sub	esp, ecx
  2593 00005AEA 89E7                <1> 	mov	edi, esp
  2594 00005AEC 89E6                <1> 	mov	esi, esp
  2595 00005AEE 66891D[FD680000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2596                              <1> 	; 11/11/2015
  2597 00005AF5 8A25[C8680000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2598                              <1> 	; 0 = none
  2599 00005AFB FECC                <1> 	dec	ah
  2600 00005AFD 790C                <1> 	jns	short sysmsg1 
  2601 00005AFF 8A1D[E7680000]      <1> 	mov	bl, [u.uno] ; process number	
  2602 00005B05 8AA3[F3650000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2603                              <1> sysmsg1:
  2604 00005B0B 8825[EC680000]      <1> 	mov	[u.ttyn], ah
  2605                              <1> sysmsg2:
  2606 00005B11 E805F5FFFF          <1> 	call	cpass
  2607 00005B16 7416                <1> 	jz	short sysmsg5
  2608 00005B18 AA                  <1> 	stosb
  2609 00005B19 20C0                <1> 	and	al, al
  2610 00005B1B 75F4                <1> 	jnz	short sysmsg2
  2611                              <1> sysmsg3:
  2612 00005B1D 80FC07              <1> 	cmp	ah, 7 ; tty number
  2613 00005B20 7711                <1> 	ja	short sysmsg6 ; serial port
  2614 00005B22 E83E000000          <1> 	call	print_cmsg
  2615                              <1> sysmsg4:
  2616 00005B27 89EC                <1> 	mov	esp, ebp	
  2617                              <1> sysmsg8: ; 24/12/2021	
  2618 00005B29 E904D8FFFF          <1> 	jmp	sysret
  2619                              <1> sysmsg5:
  2620 00005B2E C60700              <1> 	mov	byte [edi], 0
  2621 00005B31 EBEA                <1> 	jmp	short sysmsg3
  2622                              <1> sysmsg6:
  2623 00005B33 8A06                <1> 	mov	al, [esi]
  2624 00005B35 E843FEFFFF          <1> 	call	sndc
  2625 00005B3A 72EB                <1> 	jc	short sysmsg4
  2626 00005B3C 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2627 00005B3F 76E6                <1> 	jna	short sysmsg4
  2628 00005B41 46                  <1> 	inc 	esi
  2629 00005B42 8A25[EC680000]      <1> 	mov	ah, [u.ttyn]
  2630 00005B48 EBE9                <1> 	jmp	short sysmsg6
  2631                              <1> 
  2632                              <1> sysmsgk: ; Temporary (01/07/2015)
  2633                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2634                              <1> 	; (ECX -character count- will not be considered)
  2635 00005B4A 8B35[B8680000]      <1> 	mov	esi, [u.base]
  2636 00005B50 8A25[06650000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2637 00005B56 8825[EC680000]      <1> 	mov	[u.ttyn], ah
  2638 00005B5C C605[FF680000]00    <1> 	mov	byte [u.kcall], 0
  2639 00005B63 EBB8                <1> 	jmp	short sysmsg3
  2640                              <1> 	
  2641                              <1> print_cmsg: 
  2642                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2643                              <1> 	;
  2644                              <1> 	; print message (on user's console tty) 
  2645                              <1> 	;	with requested color
  2646                              <1> 	;
  2647                              <1> 	; INPUTS:
  2648                              <1> 	;	esi = message address
  2649                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2650                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2651                              <1> 	;
  2652 00005B65 AC                  <1> 	lodsb
  2653                              <1> pcmsg1:
  2654 00005B66 56                  <1> 	push 	esi
  2655 00005B67 0FB61D[EC680000]    <1>         movzx   ebx, byte [u.ttyn]
  2656 00005B6E 8A25[07650000]      <1> 	mov	ah, [ccolor]
  2657 00005B74 E848B8FFFF          <1> 	call 	write_tty
  2658 00005B79 5E                  <1> 	pop	esi
  2659 00005B7A AC                  <1> 	lodsb
  2660 00005B7B 20C0                <1> 	and 	al, al  ; 0
  2661 00005B7D 75E7                <1> 	jnz 	short pcmsg1
  2662 00005B7F C3                  <1> 	retn
  2663                              <1> 
  2664                              <1> sysgeterr:
  2665                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.1
  2666                              <1> 	; 09/12/2015
  2667                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2668                              <1> 	; Get last error number or page fault count
  2669                              <1> 	; (for debugging)
  2670                              <1> 	;
  2671                              <1> 	; Input -> EBX = return type
  2672                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2673                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2674                              <1> 	;	   FFFFFFFEh = total page fault count
  2675                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2676                              <1> 	;
  2677                              <1> 	; Output -> EAX = last error number or page fault count
  2678                              <1> 	;	   (depending on EBX input)
  2679                              <1> 	; 	
  2680 00005B80 21DB                <1> 	and 	ebx, ebx
  2681 00005B82 750F                <1> 	jnz	short glerr_2
  2682                              <1> glerr_0:
  2683 00005B84 A1[ED680000]        <1> 	mov	eax, [u.error]
  2684                              <1> glerr_1:
  2685 00005B89 A3[98680000]        <1> 	mov	[u.r0], eax
  2686                              <1>  	;retn
  2687                              <1> 	; 16/02/2022 (BugFix)
  2688 00005B8E E99FD7FFFF          <1> 	jmp	sysret
  2689                              <1> glerr_2:
  2690 00005B93 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2691 00005B94 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2692 00005B96 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2693 00005B97 75EB                <1> 	jnz	short glerr_0
  2694 00005B99 A1[8C650000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2695 00005B9E EBE9                <1>         jmp     short glerr_1
  2696                              <1> glerr_3:
  2697 00005BA0 A1[01690000]        <1> 	mov 	eax, [u.pfcount]
  2698 00005BA5 EBE2                <1> 	jmp	short glerr_1
  2699                              <1> 
  2700                              <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2701                              <1> ;	     - PRINTER BIOS (Functions)		
  2702                              <1> 
  2703                              <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 
  2704                              <1> ;
  2705                              <1> ;--- INT 17 H ------------------------------------------------------------------
  2706                              <1> ; PRINTER_IO								       :
  2707                              <1> ;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
  2708                              <1> ; INPUT 								       :
  2709                              <1> ;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
  2710                              <1> ;		    ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT)  :
  2711                              <1> ;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
  2712                              <1> ;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
  2713                              <1> ;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
  2714                              <1> ;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
  2715                              <1> ;		   7	   6	   5	   4	   3	   2-1	   0	       :
  2716                              <1> ;		   |	   |	   |	   |	   |	   |	   |_TIME OUT  :
  2717                              <1> ;		   |	   |	   |	   |	   |	   |		       :
  2718                              <1> ;		   |	   |	   |	   |	   |	   |_ UNUSED	       :
  2719                              <1> ;		   |	   |	   |	   |	   |			       :
  2720                              <1> ;		   |	   |	   |	   |	   |_ 1 = I/O ERROR	       :
  2721                              <1> ;		   |	   |	   |	   |				       :
  2722                              <1> ;		   |	   |	   |	   |_ 1 = SELECTED		       :
  2723                              <1> ;		   |	   |	   |					       :
  2724                              <1> ;		   |	   |	   |_ 1 = OUT OF PAPER			       :
  2725                              <1> ;		   |	   |						       :
  2726                              <1> ;		   |	   |_ 1 = ACKNOWLEDGE				       :
  2727                              <1> ;		   |							       :
  2728                              <1> ;		   |_ 1 = NOT BUSY					       :
  2729                              <1> ;									       :
  2730                              <1> ;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
  2731                              <1> ;		IN @PRINTER_BASE AREA					       :
  2732                              <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
  2733                              <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
  2734                              <1> ;									       :
  2735                              <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT	       :
  2736                              <1> ; TIME OUT WAITS. DEFAULT=20 * 4					       :
  2737                              <1> ;									       :
  2738                              <1> ; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
  2739                              <1> ;		ALL OTHERS UNCHANGED					       :
  2740                              <1> ;-------------------------------------------------------------------------------
  2741                              <1> 
  2742                              <1> int17h:
  2743                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2744                              <1> 	; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985)
  2745                              <1> 	;
  2746                              <1> 	; (Default printer port: 378h) ; LPT1
  2747                              <1> 	; (Number of printers = 1)
  2748                              <1> 	
  2749                              <1> 	PRINTER_BASE equ 378h ; LPT1
  2750                              <1> 	;PRINT_TIM_OUT equ 4*80*65536 
  2751                              <1> 			; (Ref: IBM PC-AT BIOS v2 PRT.ASM)	 
  2752                              <1> 
  2753                              <1> 	PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY
  2754                              <1> 			; (Ref: AWARD BIOS 1999 ATORGS.ASM)		
  2755                              <1> 
  2756                              <1> 	; INPUT:
  2757                              <1> 	;	ah = 0 -> print the character in AL 
  2758                              <1> 	;		 (sys write with write count >0)
  2759                              <1> 	;	ah = 1 -> initialize printer port
  2760                              <1> 	;		 (sys open)	
  2761                              <1> 	;	ah = 2 -> read the printer status 
  2762                              <1> 	;		 (sys write with write count = 0)
  2763                              <1> 	; OUTPUT:
  2764                              <1> 	;	ah = printer status
  2765                              <1> 
  2766                              <1> 	; Modified registers: eax, ecx, edx
  2767                              <1> 
  2768                              <1> PRINTER_IO_1:
  2769 00005BA7 08E4                <1> 	or	ah, ah
  2770 00005BA9 7417                <1> 	jz	short _b20
  2771 00005BAB FECC                <1> 	dec	ah
  2772 00005BAD 7444                <1> 	jz	short _b80
  2773                              <1> 	;dec 	ah
  2774                              <1> 	;jz	short _b50
  2775                              <1> _b50:
  2776                              <1> 	;-----	PRINTER STATUS
  2777                              <1> B50:
  2778 00005BAF 50                  <1> 	push	eax		; SAVE (AL) REGISTER
  2779                              <1> B60:
  2780 00005BB0 66BA7903            <1> 	mov	dx, PRINTER_BASE+1
  2781                              <1> 				; GET PRINTER ATTACHMENT BASE ADDRESS
  2782                              <1> 				; POINT TO CONTROL PORT
  2783 00005BB4 EC                  <1> 	in	al, dx		; PRE-CHARGE +BUSY LINE IF FLOATING
  2784 00005BB5 EC                  <1> 	in	al, dx		; GET PRINTER STATUS HARDWARE BITS
  2785 00005BB6 88C4                <1> 	mov	ah, al		; SAVE
  2786 00005BB8 80E4F8              <1> 	and	ah, 0F8h	; TURN OFF UNUSED BITS
  2787                              <1> B70:
  2788 00005BBB 5A                  <1> 	pop	edx		; RECOVER (AL) REGISTER
  2789 00005BBC 88D0                <1> 	mov	al, dl		; MOVE CHARACTER INTO (AL)
  2790 00005BBE 80F448              <1> 	xor	ah, 48h		; FLIP A COUPLE OF BITS
  2791                              <1> B10:
  2792 00005BC1 C3                  <1> 	retn			; RETURN FROM ROUTINE WITH STATUS IN AH
  2793                              <1> _b20:
  2794                              <1> 	;-----	PRINT THE CHARACTER IN (AL)
  2795 00005BC2 B9A08C0000          <1> 	mov	ecx, PRINT_TIM_OUT ; (1 second)
  2796                              <1> B20:
  2797 00005BC7 50                  <1> 	push	eax		; SAVE VALUE TO PRINT
  2798 00005BC8 66BA7803            <1> 	mov	dx, PRINTER_BASE
  2799 00005BCC EE                  <1> 	out	dx, al		; OUTPUT CHARACTER TO DATA PORT
  2800 00005BCD FEC2                <1> 	inc	dl		; POINT TO STATUS PORT
  2801                              <1> 
  2802                              <1> 	;-----	CHECK FOR PRINTER BUSY
  2803                              <1> B25:
  2804                              <1> 	;-----	WAIT BUSY
  2805                              <1> B35:
  2806 00005BCF EC                  <1> 	in	al, dx		; GET STATUS
  2807 00005BD0 88C4                <1> 	mov	ah, al		; STATUS TO (AH) ALSO
  2808 00005BD2 A880                <1> 	test	al, 80h		; IS THE PRINTER CURRENTLY BUSY? (*)
  2809 00005BD4 750F                <1> 	jnz	short B40	; GO TO OUTPUT STROBE
  2810 00005BD6 E831000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2811 00005BDB E2F2                <1> 	loop	B35		; LOOP IF YES (*)
  2812                              <1> 
  2813 00005BDD 80CC01              <1> 	or	ah, 1		; SET ERROR FLAG
  2814 00005BE0 80E4F9              <1> 	and	ah, 0F9h	; TURN OFF THE UNUSED BITS
  2815 00005BE3 EBD6                <1> 	jmp	short B70	; RETURN WITH ERROR FLAG SET
  2816                              <1> 
  2817                              <1> B40:				; SEND STROBE PULSE
  2818 00005BE5 B00D                <1> 	mov	al, 0Dh		; SET THE STROBE LOW (BIT ON)
  2819 00005BE7 6642                <1> 	inc	dx		; OUTPUT STROBE TO CONTROL PORT
  2820 00005BE9 FA                  <1> 	cli			; PREVENT INTERRUPT PULSE STRETCHING
  2821 00005BEA EE                  <1> 	out	dx, al		; OUTPUT STROBE BIT > 1us < 5us
  2822                              <1> 	; IODELAY
  2823                              <1> 	;jmp	short $+2	; I/O DELAY TO ALLOW FOR LINE LOADING
  2824                              <1> 	;jmp	short $+2	; AND FOR CORRECT PULSE WIDTH
  2825                              <1> 	; NEWIODELAY
  2826 00005BEB E6EB                <1> 	out	0EBh, al
  2827                              <1> 
  2828 00005BED B00C                <1> 	mov	al, 0Ch		; SET THE -STROBE HIGH
  2829 00005BEF EE                  <1> 	out	dx, al
  2830 00005BF0 FB                  <1> 	sti			; INTERRUPTS BACK ON
  2831                              <1> 	;pop	eax		; RECOVER THE OUTPUT CHAR
  2832                              <1> 	;jmp	short B50
  2833 00005BF1 EBBD                <1> 	jmp	short B60
  2834                              <1> 
  2835                              <1> _b80:
  2836                              <1> 	;-----	INITIALIZE THE PRINTER PORT
  2837                              <1> B80:
  2838 00005BF3 50                  <1> 	push	eax		; SAVE (AL)
  2839 00005BF4 66BA7A03            <1> 	mov	dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT
  2840 00005BF8 B008                <1> 	mov	al, 8		; SET INIT LINE LOW
  2841 00005BFA EE                  <1> 	out	dx, al
  2842                              <1> 	;mov	eax, 1000*4	; ADJUST FOR INITIALIZATION DELAY LOOP
  2843 00005BFB B989080000          <1> 	mov	ecx, WAIT_PRN_INIT ; (65536 micro seconds)
  2844                              <1> B90:				; INIT_LOOP
  2845                              <1> 	;dec	eax		; LOOP FOR RESET TO TAKE
  2846                              <1> 	;jnz	short B90	; INIT_LOOP
  2847 00005C00 E807000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2848 00005C05 E2F9                <1> 	loop	B90	
  2849 00005C07 B00C                <1> 	mov	al, 0Ch		; NO INTERRUPTS, NON AUTO LF, INIT HIGH
  2850 00005C09 EE                  <1> 	out	dx, al
  2851 00005C0A EBA4                <1> 	jmp	short B60	; EXIT THROUGH STATUS ROUTINE
  2852                              <1> 
  2853                              <1> 
  2854                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2855                              <1> ; -------------------------------------------------------------------
  2856                              <1> ;
  2857                              <1> ;;Wait while printer initializes should be 65,536 microseconds.
  2858                              <1> ;;65536/30 = 2185
  2859                              <1> ;			PUBLIC	WAIT_PRN_INIT_LO
  2860                              <1> ;WAIT_PRN_INIT_LO	DW	2185
  2861                              <1> ;			PUBLIC	WAIT_PRN_INIT_HI
  2862                              <1> ;WAIT_PRN_INIT_HI	DW	0
  2863                              <1> ;
  2864                              <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022
  2865                              <1> ;
  2866                              <1> ;;Wait for printer not busy should be 1,080,000 microseconds.
  2867                              <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us.
  2868                              <1> ;;1,080,000 / 30 = 36,000
  2869                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_LO
  2870                              <1> ;WAIT_PRN_NBUSY_LO	DW	36000
  2871                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_HI
  2872                              <1> ;WAIT_PRN_NBUSY_HI	DB	0
  2873                              <1> ;
  2874                              <1> ;WAIT_PRN_NBUSY	equ 36000 ; 12/06/2022
  2875                              <1> 
  2876                              <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999)
  2877                              <1> ; ------------------------------------------
  2878                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2879                              <1> ;   	INPUT: BX:CX = number of refresh periods to wait
  2880                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2881                              <1> ;	OUTPUT: BX:CX destroyed.
  2882                              <1> ;
  2883                              <1> ;	SAVES:	AX (except when NO STACK)
  2884                              <1> ;
  2885                              <1> ;	NOTES:	This routine can be (and is) used with no stack. When
  2886                              <1> ;		used this way, AX is assumed to be destroyed.
  2887                              <1> 
  2888                              <1> WAIT_REFRESH:
  2889                              <1> 	; 13/06/2022
  2890                              <1> 	; Modified for Retro UNIX 386 v1.1
  2891                              <1> 	
  2892                              <1> 	; (wait for 30 micro seconds)
  2893                              <1> 
  2894                              <1> 	SYS1	equ 61h ; PORT_B
  2895                              <1> 
  2896                              <1> WR_SHORT:
  2897 00005C0C 50                  <1> 	push	eax
  2898                              <1> WR_STAT_0:
  2899 00005C0D E461                <1> 	in	al, SYS1	; wait for high to low
  2900 00005C0F A810                <1> 	test	al, 10h		; transition on memory
  2901 00005C11 75FA                <1> 	jnz	short WR_STAT_0 
  2902                              <1> WR_STAT_1:
  2903 00005C13 E461                <1> 	in	al, SYS1
  2904 00005C15 A810                <1> 	test	al, 10h
  2905 00005C17 74FA                <1> 	jz	short WR_STAT_1
  2906 00005C19 58                  <1> 	pop	eax
  2907 00005C1A C3                  <1> 	retn
  2114                                  
  2115                                  ; 07/03/2015
  2116                                  ; Temporary Code
  2117                                  display_disks:
  2118 00005C1B 803D[CE5F0000]00        	cmp 	byte [fd0_type], 0
  2119 00005C22 7605                    	jna 	short ddsks1
  2120 00005C24 E87D000000              	call	pdskm
  2121                                  ddsks1:
  2122 00005C29 803D[CF5F0000]00        	cmp	byte [fd1_type], 0
  2123 00005C30 760C                    	jna	short ddsks2
  2124 00005C32 C605[BF610000]31        	mov	byte [dskx], '1'
  2125 00005C39 E868000000              	call	pdskm
  2126                                  ddsks2:
  2127 00005C3E 803D[D05F0000]00        	cmp	byte [hd0_type], 0
  2128 00005C45 7654                    	jna	short ddsk6
  2129 00005C47 66C705[BD610000]68-     	mov	word [dsktype], 'hd'
  2129 00005C4F 64                 
  2130 00005C50 C605[BF610000]30        	mov	byte [dskx], '0'
  2131 00005C57 E84A000000              	call	pdskm
  2132                                  ddsks3:
  2133 00005C5C 803D[D15F0000]00        	cmp	byte [hd1_type], 0
  2134 00005C63 7636                    	jna	short ddsk6
  2135 00005C65 C605[BF610000]31        	mov	byte [dskx], '1'
  2136 00005C6C E835000000              	call	pdskm
  2137                                  ddsks4:
  2138 00005C71 803D[D25F0000]00        	cmp	byte [hd2_type], 0
  2139 00005C78 7621                    	jna	short ddsk6
  2140 00005C7A C605[BF610000]32        	mov	byte [dskx], '2'
  2141 00005C81 E820000000              	call	pdskm
  2142                                  ddsks5:
  2143 00005C86 803D[D35F0000]00        	cmp	byte [hd3_type], 0
  2144 00005C8D 760C                    	jna	short ddsk6
  2145 00005C8F C605[BF610000]33        	mov	byte [dskx], '3'
  2146 00005C96 E80B000000              	call	pdskm
  2147                                  ddsk6:
  2148 00005C9B BE[CE610000]            	mov	esi, nextline
  2149 00005CA0 E806000000              	call	pdskml
  2150                                  pdskm_ok:
  2151 00005CA5 C3                      	retn
  2152                                  pdskm:
  2153 00005CA6 BE[BB610000]            	mov	esi, dsk_ready_msg
  2154                                  pdskml:	
  2155 00005CAB AC                      	lodsb
  2156 00005CAC 08C0                    	or	al, al
  2157 00005CAE 74F5                    	jz	short pdskm_ok
  2158 00005CB0 56                      	push	esi
  2159 00005CB1 31DB                    	xor	ebx, ebx ; 0
  2160                                  			; Video page 0 (bl=0)
  2161 00005CB3 B407                    	mov	ah, 07h ; Black background, 
  2162                                  			; light gray forecolor
  2163 00005CB5 E807B7FFFF              	call	write_tty
  2164 00005CBA 5E                      	pop	esi
  2165 00005CBB EBEE                    	jmp	short pdskml
  2166                                  
  2167 00005CBD 90<rep 3h>              align 16
  2168                                  
  2169                                  gdt:	; Global Descriptor Table
  2170                                  	; (30/07/2015, conforming cs)
  2171                                  	; (26/03/2015)
  2172                                  	; (24/03/2015, tss)
  2173                                  	; (19/03/2015)
  2174                                  	; (29/12/2013)
  2175                                  	;
  2176 00005CC0 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2177                                  	; 18/08/2014
  2178                                  			; 8h kernel code segment, base = 00000000h		
  2179 00005CC8 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2180                                  			; 10h kernel data segment, base = 00000000h	
  2181 00005CD0 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2182                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2183 00005CD8 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2184                                  			; 23h user data segment, base address = 400000h ; CORE
  2185 00005CE0 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2186                                  			; Task State Segment
  2187 00005CE8 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2188                                  			       ;  no IO permission in ring 3)
  2189                                  gdt_tss0:
  2190 00005CEA 0000                    	dw 0  ; TSS base address, bits 0-15 
  2191                                  gdt_tss1:
  2192 00005CEC 00                      	db 0  ; TSS base address, bits 16-23 
  2193                                  	      		; 49h	
  2194 00005CED E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2195 00005CEE 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2196                                  gdt_tss2:
  2197 00005CEF 00                      	db 0  ; TSS base address, bits 24-31 
  2198                                  
  2199                                  gdt_end:
  2200                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2201                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2202                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2203                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2204                                  
  2205                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2206                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2207                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2208                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2209                                  		; W= Writeable, A= Accessed
  2210                                  	
  2211                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2212                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2213                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2214                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2215                                  
  2216                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2217                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2218                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2219                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2220                                  	
  2221                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2222                                  
  2223                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2224                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2225                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2226                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2227                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2228                                  		; AVL= Available to programmers	
  2229                                  
  2230                                  gdtd:
  2231 00005CF0 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2232 00005CF2 [C05C0000]                      dd gdt			; Address of the GDT
  2233                                  
  2234                                  	; 20/08/2014
  2235                                  idtd:
  2236 00005CF6 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2237 00005CF8 [70620000]                      dd idt			; Address of the IDT
  2238                                  
  2239                                  Align 4
  2240                                  
  2241                                  	; 21/08/2014
  2242                                  ilist:
  2243                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2244                                  	;
  2245                                  	; Exception list
  2246                                  	; 25/08/2014	
  2247 00005CFC [24080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2248 00005D00 [2B080000]              	dd	exc1	
  2249 00005D04 [32080000]              	dd 	exc2	
  2250 00005D08 [39080000]              	dd	exc3	
  2251 00005D0C [3D080000]              	dd	exc4	
  2252 00005D10 [41080000]              	dd	exc5	
  2253 00005D14 [45080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2254 00005D18 [49080000]              	dd	exc7	
  2255 00005D1C [4D080000]              	dd	exc8	
  2256 00005D20 [51080000]              	dd	exc9	
  2257 00005D24 [55080000]              	dd 	exc10	
  2258 00005D28 [59080000]              	dd	exc11
  2259 00005D2C [5D080000]              	dd	exc12
  2260 00005D30 [61080000]              	dd	exc13	; 0Dh, General Protection Fault
  2261 00005D34 [65080000]              	dd 	exc14	; 0Eh, Page Fault
  2262 00005D38 [69080000]              	dd	exc15
  2263 00005D3C [6D080000]              	dd	exc16
  2264 00005D40 [71080000]              	dd	exc17
  2265 00005D44 [75080000]              	dd 	exc18
  2266 00005D48 [79080000]              	dd	exc19
  2267 00005D4C [7D080000]              	dd 	exc20
  2268 00005D50 [81080000]              	dd	exc21
  2269 00005D54 [85080000]              	dd	exc22
  2270 00005D58 [89080000]              	dd	exc23
  2271 00005D5C [8D080000]              	dd 	exc24
  2272 00005D60 [91080000]              	dd	exc25
  2273 00005D64 [95080000]              	dd	exc26
  2274 00005D68 [99080000]              	dd	exc27
  2275 00005D6C [9D080000]              	dd 	exc28
  2276 00005D70 [A1080000]              	dd	exc29
  2277 00005D74 [A5080000]              	dd 	exc30
  2278 00005D78 [A9080000]              	dd	exc31
  2279                                  	; Interrupt list
  2280 00005D7C [5F060000]              	dd	timer_int	; INT 20h
  2281                                  		;dd	irq0	
  2282 00005D80 [630B0000]              	dd	keyb_int	; 27/08/2014
  2283                                  		;dd	irq1
  2284 00005D84 [7E070000]              	dd	irq2
  2285                                  		; COM2 int
  2286 00005D88 [82070000]              	dd	irq3
  2287                                  		; COM1 int
  2288 00005D8C [8D070000]              	dd	irq4
  2289 00005D90 [98070000]              	dd	irq5
  2290                                  ;DISKETTE_INT: ;06/02/2015
  2291 00005D94 [40200000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2292                                  		;dd	irq6
  2293                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2294                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2295 00005D98 [140B0000]              	dd	default_irq7	; 25/02/2015
  2296                                  		;dd	irq7
  2297                                  ; Real Time Clock Interrupt
  2298 00005D9C [B2090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2299                                  		;dd	irq8	; INT 28h
  2300 00005DA0 [A8070000]              	dd	irq9
  2301 00005DA4 [AC070000]              	dd	irq10
  2302 00005DA8 [B0070000]              	dd	irq11
  2303 00005DAC [B4070000]              	dd	irq12
  2304 00005DB0 [B8070000]              	dd	irq13
  2305                                  ;HDISK_INT1:  ;06/02/2015 	
  2306 00005DB4 [BA250000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2307                                  		;dd	irq14
  2308                                  ;HDISK_INT2:  ;06/02/2015
  2309 00005DB8 [DD250000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2310                                  		;dd	irq15	; INT 2Fh
  2311                                  		; 14/08/2015
  2312 00005DBC [1A320000]              	dd	sysent		; INT 30h (system calls)
  2313                                  	
  2314                                  	;dd	ignore_int
  2315 00005DC0 00000000                	dd	0
  2316                                  
  2317                                  ;;;
  2318                                  ;;; 11/03/2015
  2319                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2320                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - KYBDATA.INC
  2321                              <1> ; Last Modification: 13/06/2022
  2322                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2323                              <1> ;
  2324                              <1> ; ///////// KEYBOARD DATA ///////////////
  2325                              <1> 
  2326                              <1> ; 11/03/2015
  2327                              <1> ; 05/12/2014
  2328                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2329                              <1> ; 03/06/86  KEYBOARD BIOS
  2330                              <1> 
  2331                              <1> ;---------------------------------------------------------------------------------
  2332                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2333                              <1> ;---------------------------------------------------------------------------------
  2334                              <1> 
  2335                              <1> ;-----	TABLES FOR ALT CASE ------------
  2336                              <1> ;-----	ALT-INPUT-TABLE 
  2337 00005DC4 524F50514B          <1> K30:	db	82,79,80,81,75
  2338 00005DC9 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2339                              <1> ;-----	SUPER-SHIFT-TABLE 
  2340 00005DCE 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2341 00005DD4 161718191E1F        <1> 	db	22,23,24,25,30,31
  2342 00005DDA 202122232425        <1> 	db	32,33,34,35,36,37
  2343 00005DE0 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2344 00005DE6 3132                <1> 	db	49,50
  2345                              <1> 
  2346                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2347                              <1> ;-----	KEY_TABLE 
  2348 00005DE8 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2349 00005DE9 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2350 00005DEE 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2351                              <1> _K6L    equ     $-_K6
  2352                              <1> 
  2353                              <1> ;-----	MASK_TABLE
  2354 00005DF0 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2355 00005DF1 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2356 00005DF6 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2357                              <1> 
  2358                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2359 00005DF8 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2360 00005DFE 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2361                              <1> 	;db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2362 00005E04 FF7F94111705        <1> 	db	-1,127,148,17,23,5 ; 13/06/2022
  2363 00005E0A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2364 00005E10 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2365 00005E16 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2366 00005E1C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2367 00005E22 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2368 00005E28 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2369 00005E2E 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2370                              <1> 	;				;----- FUNCTIONS ------		
  2371 00005E32 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2372 00005E38 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2373 00005E3E 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2374 00005E44 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2375 00005E4A 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2376                              <1> 
  2377                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2378 00005E50 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2378 00005E59 39302D3D0809        <1>
  2379 00005E5F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2379 00005E68 705B5D0DFF61736466- <1>
  2379 00005E71 67686A6B6C3B27      <1>
  2380 00005E78 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2380 00005E81 6D2C2E2FFF2AFF20FF  <1>
  2381                              <1> ;-----	LC TABLE SCAN
  2382 00005E8A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2383 00005E8F 4041424344          <1> 	db	64,65,66,67,68
  2384 00005E94 FFFF                <1> 	db	-1,-1			; NL, SL
  2385                              <1> 
  2386                              <1> ;-----	KEYPAD TABLE
  2387 00005E96 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2388 00005E9C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2389 00005EA3 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2390                              <1> 
  2391                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2392 00005EA8 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2392 00005EB1 28295F2B0800        <1>
  2393 00005EB7 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2393 00005EC0 507B7D0DFF41534446- <1>
  2393 00005EC9 47484A4B4C3A22      <1>
  2394 00005ED0 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2394 00005ED9 4D3C3E3FFF2AFF20FF  <1>
  2395                              <1> ;-----	UC TABLE SCAN
  2396 00005EE2 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2397 00005EE7 595A5B5C5D          <1> 	db	89,90,91,92,93
  2398 00005EEC FFFF                <1> 	db	-1,-1			; NL, SL
  2399                              <1> 
  2400                              <1> ;-----	NUM STATE TABLE
  2401 00005EEE 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2401 00005EF7 3233302E            <1>
  2402                              <1> 	;
  2403 00005EFB FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2404                              <1> 
  2405                              <1> Align	4
  2406                              <1> ;----------------------------------------
  2407                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2408                              <1> ;----------------------------------------
  2409 00005F00 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2410 00005F01 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2411                              <1> 				; (29h default setting for video mode 3)
  2412                              <1> 				; Mode Select register Bits
  2413                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2414                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2415                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2416                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2417                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2418                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2419                              <1> 				;   BIT 6, 7 - Not Used
  2420                              <1> 
  2421                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2422                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2423                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2424                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2425                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2426                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2427                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2428                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2429                              <1> ; Mode & 37h = Video signal OFF
  2430                              <1> 			
  2431                              <1> 
  2432                              <1> ; 26/08/2014
  2433                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2434                              <1> ; Derived from IBM "pc-at" 
  2435                              <1> ; rombios source code (06/10/1985)
  2436                              <1> ; 'dseg.inc'
  2437                              <1> 
  2438                              <1> ;---------------------------------------;
  2439                              <1> ;	SYSTEM DATA AREA		;
  2440                              <1> ;----------------------------------------
  2441 00005F02 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2442                              <1> 
  2443                              <1> ;----------------------------------------
  2444                              <1> ;	KEYBOARD DATA AREAS		;
  2445                              <1> ;----------------------------------------
  2446                              <1> 
  2447 00005F03 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2448 00005F04 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2449 00005F05 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2450 00005F06 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2451 00005F07 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2452 00005F08 [185F0000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2453 00005F0C [385F0000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2454 00005F10 [185F0000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2455 00005F14 [185F0000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2456                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2457 00005F18 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2458                              <1> 
  2459                              <1> ; /// End Of KEYBOARD DATA ///
  2320                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2321                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2322                              <1> ; Last Modification: 11/03/2015
  2323                              <1> ;		    (Data section for 'VIDEO.INC')	
  2324                              <1> ;
  2325                              <1> ; ///////// VIDEO DATA ///////////////
  2326                              <1> 
  2327                              <1> video_params:
  2328                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2329                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2330                              <1> 	; VIDEO MODE 3
  2331 00005F38 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2332 00005F3F 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2333 00005F44 00000000            <1> 	db	0,0,0,0
  2334                              <1> 
  2335                              <1> ; /// End Of VIDEO DATA ///
  2321                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2322                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2323                              <1> ; Last Modification: 11/03/2015
  2324                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2325                              <1> ;
  2326                              <1> ; *****************************************************************************
  2327                              <1> 
  2328                              <1> ;----------------------------------------
  2329                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2330                              <1> ;	REFERENCED BY POST & BIOS	:
  2331                              <1> ;----------------------------------------
  2332                              <1> 
  2333 00005F48 [AB5F0000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2334                              <1> 
  2335                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2336                              <1> ;----------------------------------------------------------------
  2337                              <1> ; DISK_BASE							:
  2338                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2339                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2340                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2341                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2342                              <1> ;----------------------------------------------------------------
  2343                              <1> 
  2344                              <1> ;DISK_BASE:	
  2345                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2346                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2347                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2348                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2349                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2350                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2351                              <1> ;	DB	01BH		; GAP LENGTH
  2352                              <1> ;	DB	0FFH		; DTL
  2353                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2354                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2355                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2356                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2357                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2358                              <1> 
  2359                              <1> ;----------------------------------------
  2360                              <1> ;	ROM BIOS DATA AREAS		:
  2361                              <1> ;----------------------------------------
  2362                              <1> 
  2363                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2364                              <1> 
  2365                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2366                              <1> 
  2367                              <1> ;----------------------------------------
  2368                              <1> ;	DISKETTE DATA AREAS		:
  2369                              <1> ;----------------------------------------
  2370                              <1> 
  2371                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2372                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2373                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2374                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2375                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2376                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2377                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2378                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2379                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2380                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2381                              <1> 
  2382                              <1> ;----------------------------------------
  2383                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2384                              <1> ;----------------------------------------
  2385                              <1> 
  2386                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2387                              <1> 
  2388                              <1> ;----------------------------------------
  2389                              <1> ;	TIMER DATA AREA 		:
  2390                              <1> ;----------------------------------------
  2391                              <1> 
  2392                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2393                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2394                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2395                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2396                              <1> 
  2397                              <1> ;----------------------------------------
  2398                              <1> ;	ADDITIONAL MEDIA DATA		:
  2399                              <1> ;----------------------------------------
  2400                              <1> 
  2401                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2402                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2403                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2404                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2405                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2406                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2407                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2408                              <1> 
  2409                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2410                              <1> 
  2411                              <1> ;--------------------------------------------------------
  2412                              <1> ;	DRIVE TYPE TABLE				:
  2413                              <1> ;--------------------------------------------------------
  2414                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2415                              <1> DR_TYPE:
  2416 00005F4C 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2417                              <1>                 ;DW      MD_TBL1
  2418 00005F4D [6A5F0000]          <1> 		dd	MD_TBL1
  2419 00005F51 82                  <1> 		DB	02+BIT7ON
  2420                              <1> 		;DW      MD_TBL2
  2421 00005F52 [775F0000]          <1>                 dd      MD_TBL2
  2422 00005F56 02                  <1> DR_DEFAULT:	DB	02
  2423                              <1>                 ;DW      MD_TBL3
  2424 00005F57 [845F0000]          <1> 		dd      MD_TBL3
  2425 00005F5B 03                  <1> 		DB	03
  2426                              <1>                 ;DW      MD_TBL4
  2427 00005F5C [915F0000]          <1> 		dd      MD_TBL4
  2428 00005F60 84                  <1> 		DB	04+BIT7ON
  2429                              <1>                 ;DW      MD_TBL5
  2430 00005F61 [9E5F0000]          <1> 		dd      MD_TBL5
  2431 00005F65 04                  <1> 		DB	04
  2432                              <1>                 ;DW      MD_TBL6
  2433 00005F66 [AB5F0000]          <1> 		dd      MD_TBL6
  2434                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2435                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2436                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2437                              <1> ;--------------------------------------------------------
  2438                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2439                              <1> ;--------------------------------------------------------
  2440                              <1> ;--------------------------------------------------------
  2441                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2442                              <1> ;--------------------------------------------------------
  2443                              <1> MD_TBL1:        
  2444 00005F6A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2445 00005F6B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2446 00005F6C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2447 00005F6D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2448 00005F6E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2449 00005F6F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2450 00005F70 FF                  <1> 	DB	0FFH		; DTL
  2451 00005F71 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2452 00005F72 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2453 00005F73 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2454 00005F74 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2455 00005F75 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2456 00005F76 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2457                              <1> ;--------------------------------------------------------
  2458                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2459                              <1> ;--------------------------------------------------------
  2460                              <1> MD_TBL2:        
  2461 00005F77 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2462 00005F78 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2463 00005F79 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2464 00005F7A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2465 00005F7B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2466 00005F7C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2467 00005F7D FF                  <1> 	DB	0FFH		; DTL
  2468 00005F7E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2469 00005F7F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2470 00005F80 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2471 00005F81 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2472 00005F82 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2473 00005F83 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2474                              <1> ;--------------------------------------------------------
  2475                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2476                              <1> ;--------------------------------------------------------
  2477                              <1> MD_TBL3:
  2478 00005F84 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2479 00005F85 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2480 00005F86 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2481 00005F87 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2482 00005F88 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2483 00005F89 1B                  <1> 	DB	01BH		; GAP LENGTH
  2484 00005F8A FF                  <1> 	DB	0FFH		; DTL
  2485 00005F8B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2486 00005F8C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2487 00005F8D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2488 00005F8E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2489 00005F8F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2490 00005F90 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2491                              <1> ;--------------------------------------------------------
  2492                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2493                              <1> ;--------------------------------------------------------
  2494                              <1> MD_TBL4:
  2495 00005F91 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2496 00005F92 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2497 00005F93 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2498 00005F94 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2499 00005F95 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2500 00005F96 2A                  <1> 	DB	02AH		; GAP LENGTH
  2501 00005F97 FF                  <1> 	DB	0FFH		; DTL
  2502 00005F98 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2503 00005F99 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2504 00005F9A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2505 00005F9B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2506 00005F9C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2507 00005F9D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2508                              <1> ;--------------------------------------------------------
  2509                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2510                              <1> ;--------------------------------------------------------
  2511                              <1> MD_TBL5:
  2512 00005F9E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2513 00005F9F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2514 00005FA0 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2515 00005FA1 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2516 00005FA2 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2517 00005FA3 2A                  <1> 	DB	02AH		; GAP LENGTH
  2518 00005FA4 FF                  <1> 	DB	0FFH		; DTL
  2519 00005FA5 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2520 00005FA6 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2521 00005FA7 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2522 00005FA8 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2523 00005FA9 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2524 00005FAA 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2525                              <1> ;--------------------------------------------------------
  2526                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2527                              <1> ;--------------------------------------------------------
  2528                              <1> MD_TBL6:
  2529 00005FAB AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2530 00005FAC 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2531 00005FAD 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2532 00005FAE 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2533 00005FAF 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2534 00005FB0 1B                  <1> 	DB	01BH		; GAP LENGTH
  2535 00005FB1 FF                  <1> 	DB	0FFH		; DTL
  2536 00005FB2 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2537 00005FB3 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2538 00005FB4 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2539 00005FB5 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2540 00005FB6 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2541 00005FB7 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2542                              <1> 
  2543                              <1> 
  2544                              <1> ; << diskette.inc >>
  2545                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2546                              <1> ;
  2547                              <1> ;----------------------------------------
  2548                              <1> ;	ROM BIOS DATA AREAS		:
  2549                              <1> ;----------------------------------------
  2550                              <1> 
  2551                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2552                              <1> 
  2553                              <1> ;----------------------------------------
  2554                              <1> ;	FIXED DISK DATA AREAS		:
  2555                              <1> ;----------------------------------------
  2556                              <1> 
  2557                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2558                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2559                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2560                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2561                              <1> 
  2562                              <1> ;----------------------------------------
  2563                              <1> ;	ADDITIONAL MEDIA DATA		:
  2564                              <1> ;----------------------------------------
  2565                              <1> 
  2566                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2567                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2568                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2569                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2570                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2571                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2572                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2573                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2574                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2575                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2576                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2577                              <1> 
  2578                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2579                              <1> ;
  2580                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2581                              <1> 
  2582                              <1> ERR_TBL:
  2583 00005FB8 E0                  <1> 	db	NO_ERR
  2584 00005FB9 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2585 00005FBD 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2586                              <1> 
  2587                              <1> ; 17/12/2014 (mov ax, [cfd])
  2588                              <1> ; 11/12/2014
  2589 00005FC1 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2590                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2591 00005FC2 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2592                              <1> 					; (initial value of 'pfd 
  2593                              <1> 					; must be different then 'cfd' value
  2594                              <1> 					; to force updating/initializing
  2595                              <1> 					; current drive parameters) 
  2596 00005FC3 90                  <1> align 2
  2597                              <1> 
  2598 00005FC4 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2599                              <1> 			      ; (170h)
  2600 00005FC6 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2601                              <1> 
  2602                              <1> ; 05/01/2015 
  2603 00005FC8 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2604                              <1> 
  2605                              <1> ; *****************************************************************************
  2322                                  ;;;
  2323                                  
  2324 00005FC9 90                      Align 2
  2325                                  
  2326                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2327 00005FCA 00                      boot_drv:    db 0 ; boot drive number (physical)
  2328                                  ; 24/11/2014
  2329 00005FCB 00                      drv:	     db 0 
  2330 00005FCC 00                      last_drv:    db 0 ; last hdd
  2331 00005FCD 00                      hdc:         db 0  ; number of hard disk drives
  2332                                  		     ; (present/detected)
  2333                                  ;
  2334                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2335                                  ; Physical drive type & flags
  2336 00005FCE 00                      fd0_type:    db 0  ; floppy drive type
  2337 00005FCF 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2338                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2339                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2340                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2341                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2342 00005FD0 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2343 00005FD1 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2344 00005FD2 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2345 00005FD3 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2346                                  		     ; bit 0 - Fixed disk access subset supported
  2347                                  		     ; bit 1 - Drive locking and ejecting
  2348                                  		     ; bit 2 - Enhanced disk drive support
  2349                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2350                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2351                                  		     ; will interpret it as 'LBA ready'!)		
  2352                                  
  2353                                  ; 11/03/2015 - 10/07/2015
  2354 00005FD4 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2354 00005FDD 0000000000         
  2355 00005FE2 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2355 00005FEB 0000000000         
  2356 00005FF0 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2356 00005FF9 0000000000         
  2357 00005FFE 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2357 00006007 000000000000000000-
  2357 00006010 000000000000000000-
  2357 00006019 00                 
  2358 0000601A 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2359 00006021 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2360                                  ;
  2361                                  
  2362                                  ; 27/08/2014
  2363                                  scr_row:
  2364 00006028 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2365                                  scr_col:
  2366 0000602C 00000000                	dd 0
  2367                                  
  2368                                  ;; 14/08/2015
  2369                                  ;;msgPM:
  2370                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2371                                  msgKVER:
  2372                                  	;;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.2 [29/04/2022]", 0
  2373                                  	;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.3 [02/06/2022]", 0
  2374                                  	;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.4 [14/06/2022]", 0
  2375 00006030 526574726F20554E49-     	db "Retro UNIX 386 v1.1 - Kernel v0.2.1.5 [10/07/2022]", 0
  2375 00006039 58203338362076312E-
  2375 00006042 31202D204B65726E65-
  2375 0000604B 6C2076302E322E312E-
  2375 00006054 35205B31302F30372F-
  2375 0000605D 323032325D00       
  2376                                  
  2377 00006063 90                      Align 2
  2378                                  
  2379                                  ; 20/08/2014
  2380                                    ; /* This is the default interrupt "handler" :-) */ 
  2381                                    ; Linux v0.12 (head.s)
  2382                                  int_msg:
  2383 00006064 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2383 0000606D 6E7465727275707420-
  2383 00006076 212000             
  2384                                  
  2385 00006079 90                      Align 2  
  2386                                  
  2387                                  ; 21/08/2014
  2388                                  timer_msg:
  2389 0000607A 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2389 00006083 542032306829202120-
  2389 0000608C 54696D657220496E74-
  2389 00006095 657272757074203A20 
  2390                                  tcountstr:
  2391 0000609E 303030303020            	db "00000 "
  2392 000060A4 00                      	db 0
  2393                                  
  2394 000060A5 90                      Align 2
  2395                                  	; 21/08/2014
  2396                                  exc_msg:
  2397 000060A6 435055206578636570-     	db "CPU exception ! "
  2397 000060AF 74696F6E202120     
  2398                                  excnstr: 		; 25/08/2014
  2399 000060B6 3F3F68202045495020-     	db "??h", "  EIP : "
  2399 000060BF 3A20               
  2400                                  EIPstr: ; 29/08/2014
  2401 000060C1 00<rep Ch>              	times 12 db 0
  2402                                  rtc_msg:
  2403 000060CD 5265616C2054696D65-     	db "Real Time Clock - "
  2403 000060D6 20436C6F636B202D20 
  2404                                  datestr:
  2405 000060DF 30302F30302F303030-     	db "00/00/0000"
  2405 000060E8 30                 
  2406 000060E9 20                      	db " "
  2407                                  daystr:
  2408 000060EA 44415920                	db "DAY "
  2409                                  timestr:	
  2410 000060EE 30303A30303A3030                db "00:00:00"
  2411 000060F6 20                      	db " "
  2412 000060F7 00                      	db 0 
  2413                                  
  2414                                  daytmp:
  2415                                  	; 28/02/2015
  2416 000060F8 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2416 00006101 4F4E20545545205745-
  2416 0000610A 442054485520465249-
  2416 00006113 2053415420         
  2417                                  
  2418 00006118 FF                      ptime_seconds: db 0FFh
  2419                                  
  2420                                  	; 23/02/2015
  2421                                  	; 25/08/2014
  2422                                  ;scounter:
  2423                                  ;	db 5
  2424                                  ;	db 19
  2425                                  
  2426                                  ; 02/01/2022
  2427                                  ; 05/11/2014
  2428                                  ;msg_out_of_memory:
  2429                                  ;	db 	07h, 0Dh, 0Ah
  2430                                  ;       db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2431                                  ; 	db	0Dh, 0Ah, 0
  2432                                  	;
  2433                                  setup_error_msg:
  2434 00006119 0D0A                    	db 0Dh, 0Ah
  2435 0000611B 4469736B2053657475-     	db 'Disk Setup Error!' 
  2435 00006124 70204572726F7221   
  2436 0000612C 0D0A00                  	db 0Dh, 0Ah,0
  2437                                  
  2438                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2439                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2440                                  ;	  db 0 ; upper left row (for scroll)	
  2441                                  
  2442                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2443                                  ;	  db 24 ; lower right row (for scroll)
  2444                                  
  2445                                  
  2446                                  ; 06/11/2014 (Temporary Data)
  2447                                  ; Memory Information message
  2448                                  ; 14/08/2015
  2449                                  msg_memory_info:
  2450 0000612F 07                      	db	07h
  2451 00006130 0D0A                    	db	0Dh, 0Ah
  2452                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2453 00006132 546F74616C206D656D-     	db	"Total memory : "
  2453 0000613B 6F7279203A20       
  2454                                  mem_total_b_str: ; 10 digits
  2455 00006141 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2455 0000614A 302062797465730D0A 
  2456 00006153 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2456 0000615C 202020202020202020 
  2457                                  mem_total_p_str: ; 7 digits
  2458 00006165 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2458 0000616E 616765730D0A       
  2459 00006174 0D0A                    	db 	0Dh, 0Ah
  2460 00006176 46726565206D656D6F-     	db	"Free memory  : "
  2460 0000617F 727920203A20       
  2461                                  free_mem_b_str:  ; 10 digits
  2462 00006185 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2462 0000618E 3F2062797465730D0A 
  2463 00006197 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2463 000061A0 202020202020202020 
  2464                                  free_mem_p_str:  ; 7 digits
  2465 000061A9 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2465 000061B2 616765730D0A       
  2466 000061B8 0D0A00                  	db	0Dh, 0Ah, 0
  2467                                  
  2468                                  dsk_ready_msg:
  2469 000061BB 0D0A                    	db 	0Dh, 0Ah
  2470                                  dsktype:
  2471 000061BD 6664                    	db	'fd'
  2472                                  dskx:
  2473 000061BF 30                      	db	'0'
  2474 000061C0 20                      	db	20h
  2475 000061C1 697320524541445920-     	db 	'is READY ...'
  2475 000061CA 2E2E2E             
  2476 000061CD 00                      	db 	0
  2477                                  nextline:
  2478 000061CE 0D0A00                  	db 	0Dh, 0Ah, 0
  2479                                  
  2480                                  ; KERNEL - SYSINIT Messages
  2481                                  ; 24/08/2015
  2482                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2483                                  ; 14/07/2013
  2484                                  ;kernel_init_err_msg:
  2485                                  ;	db 0Dh, 0Ah
  2486                                  ;	db 07h
  2487                                  ;	db 'Kernel initialization ERROR !'
  2488                                  ;	db 0Dh, 0Ah, 0 
  2489                                  ; 24/08/2015
  2490                                  ;;; (temporary kernel init message has been removed
  2491                                  ;;;  from 'sys_init' code)
  2492                                  ;kernel_init_ok_msg: 
  2493                                  ;	db 0Dh, 0Ah
  2494                                  ;	db 07h
  2495                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2496                                  ;	db 0Dh, 0Ah
  2497                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2498                                  ;	db 0Dh, 0Ah, 0
  2499                                  panic_msg:
  2500 000061D1 0D0A07                  	db 0Dh, 0Ah, 07h
  2501 000061D4 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2501 000061DD 726E656C2050616E69-
  2501 000061E6 632021             
  2502 000061E9 0D0A00                  	db 0Dh, 0Ah, 0
  2503                                  etc_init_err_msg:
  2504 000061EC 0D0A                    	db 0Dh, 0Ah
  2505 000061EE 07                      	db 07h
  2506 000061EF 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2506 000061F8 74632F696E69742021-
  2506 00006201 3F                 
  2507 00006202 0D0A00                  	db 0Dh, 0Ah, 0
  2508                                  
  2509                                  ; 10/05/2015
  2510                                  badsys_msg:
  2511 00006205 0D0A                    	db 0Dh, 0Ah
  2512 00006207 07                      	db 07h
  2513 00006208 496E76616C69642053-     	db 'Invalid System Call !'
  2513 00006211 797374656D2043616C-
  2513 0000621A 6C2021             
  2514 0000621D 0D0A                    	db 0Dh, 0Ah
  2515 0000621F 4541583A20              	db 'EAX: '
  2516                                  bsys_msg_eax:
  2517 00006224 303030303030303068      	db '00000000h'
  2518 0000622D 0D0A                    	db 0Dh, 0Ah
  2519 0000622F 4549503A20              	db 'EIP: '
  2520                                  bsys_msg_eip:
  2521 00006234 303030303030303068      	db '00000000h' 
  2522 0000623D 0D0A00                  	db 0Dh, 0Ah, 0
  2523                                  
  2524                                  BSYS_M_SIZE equ $ - badsys_msg
  2525                                  
  2526                                  
  2527                                  align 2
  2528                                  
  2529                                  ; EPOCH Variables
  2530                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2531                                  ; 09/04/2013 epoch variables
  2532                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2533                                  ;
  2534 00006240 B207                    year: 	dw 1970
  2535                                  ;month: dw 1
  2536                                  ;day: 	dw 1
  2537                                  ;hour: 	dw 0
  2538                                  ;minute: dw 0
  2539                                  ;second: dw 0
  2540                                  ; 02/06/2022
  2541 00006242 01                      month:	db 1
  2542 00006243 01                      day:	db 1
  2543 00006244 01                      hour:	db 1
  2544 00006245 01                      minute: db 1
  2545 00006246 01                      second:	db 1
  2546 00006247 01                      	db 1
  2547                                  
  2548                                  DMonth:
  2549 00006248 0000                    	dw 0
  2550 0000624A 1F00                    	dw 31
  2551 0000624C 3B00                    	dw 59
  2552 0000624E 5A00                    	dw 90
  2553 00006250 7800                    	dw 120
  2554 00006252 9700                    	dw 151
  2555 00006254 B500                    	dw 181
  2556 00006256 D400                    	dw 212
  2557 00006258 F300                    	dw 243
  2558 0000625A 1101                    	dw 273
  2559 0000625C 3001                    	dw 304
  2560 0000625E 4E01                    	dw 334
  2561                                  
  2562                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
  2563                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2564 00006260 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2565                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2566 00006262 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2567 00006264 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2568                                  		   ;   between 16 MB and 4 GB.
  2569 00006266 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2570                                  
  2571                                  ; 02/01/2022
  2572                                  KEND:
  2573                                  
  2574 00006268 90<rep 8h>              align 16
  2575                                  
  2576                                  bss_start:
  2577                                  
  2578                                  ABSOLUTE bss_start
  2579                                  
  2580                                  	; 11/03/2015
  2581                                  	; Interrupt Descriptor Table (20/08/2014)
  2582                                  idt:
  2583 00006270 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2584                                  idt_end:
  2585                                  
  2586                                  ;alignb 4
  2587                                  
  2588                                  task_state_segment:
  2589                                  	; 24/03/2015
  2590 00006470 ????                    tss.link:   resw 1
  2591 00006472 ????                    	    resw 1
  2592                                  ; tss offset 4	
  2593 00006474 ????????                tss.esp0:   resd 1
  2594 00006478 ????                    tss.ss0:    resw 1
  2595 0000647A ????                    	    resw 1	
  2596 0000647C ????????                tss.esp1:   resd 1
  2597 00006480 ????                    tss.ss1:    resw 1
  2598 00006482 ????                    	    resw 1 	
  2599 00006484 ????????                tss.esp2:   resd 1
  2600 00006488 ????                    tss.ss2:    resw 1
  2601 0000648A ????                    	    resw 1
  2602                                  ; tss offset 28
  2603 0000648C ????????                tss.CR3:    resd 1
  2604 00006490 ????????                tss.eip:    resd 1
  2605 00006494 ????????                tss.eflags: resd 1
  2606                                  ; tss offset 40
  2607 00006498 ????????                tss.eax:    resd 1		 		
  2608 0000649C ????????                tss.ecx:    resd 1
  2609 000064A0 ????????                tss.edx:    resd 1
  2610 000064A4 ????????                tss.ebx:    resd 1
  2611 000064A8 ????????                tss.esp:    resd 1
  2612 000064AC ????????                tss.ebp:    resd 1
  2613 000064B0 ????????                tss.esi:    resd 1
  2614 000064B4 ????????                tss.edi:    resd 1
  2615                                  ; tss offset 72
  2616 000064B8 ????                    tss.ES:     resw 1
  2617 000064BA ????                    	    resw 1	
  2618 000064BC ????                    tss.CS:	    resw 1
  2619 000064BE ????                    	    resw 1
  2620 000064C0 ????                    tss.SS:	    resw 1
  2621 000064C2 ????                    	    resw 1
  2622 000064C4 ????                    tss.DS:	    resw 1
  2623 000064C6 ????                    	    resw 1
  2624 000064C8 ????                    tss.FS:	    resw 1
  2625 000064CA ????                    	    resw 1
  2626 000064CC ????                    tss.GS:	    resw 1
  2627 000064CE ????                    	    resw 1		
  2628 000064D0 ????                    tss.LDTR:   resw 1
  2629 000064D2 ????                    	    resw 1
  2630                                  ; tss offset 100		
  2631 000064D4 ????                    	    resw 1		
  2632 000064D6 ????                    tss.IOPB:   resw 1
  2633                                  ; tss offset 104 
  2634                                  tss_end:
  2635                                  
  2636 000064D8 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2637                                  		  ;   (Physical address = Virtual address)	 	
  2638 000064DC ????????                memory_size: resd 1 ; memory size in pages
  2639 000064E0 ????????                free_pages:  resd 1 ; number of free pages		
  2640 000064E4 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2641                                  		  ;   first free page search
  2642 000064E8 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2643                                  		  ;   next free page search will be
  2644                                  		  ; stopped after it. (end of M.A.T.)
  2645 000064EC ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2646                                  		  ; first free page search
  2647                                  		  ;   will be started on it. (for user)
  2648 000064F0 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2649                                  
  2650                                  ;;;
  2651                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2652                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2653 000064F4 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2654                                  			  ; NOTE: active page only
  2655 000064F6 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2656                                  active_page: 
  2657 00006506 ??                      ptty: 	     resb 1 	  ; current tty
  2658                                  ; 01/07/2015
  2659 00006507 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2660                                  ; 26/10/2015
  2661                                  ; 07/09/2014
  2662 00006508 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2663                                  
  2664                                  ; 21/08/2014
  2665 0000651C ????????                tcount:	     resd 1
  2666                                  
  2667                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2668 00006520 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2669                                  
  2670                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2671                                  ; (open mode locks for pseudo TTYs)
  2672                                  ; [ major tty locks (return error in any conflicts) ]
  2673 00006524 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2674                                  
  2675                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2676                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2677 00006538 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2678                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2679                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2680                                  ;; 0 means serial port is not available 
  2681                                  ;;comprm: ; 25/06/2014
  2682 00006542 ??                      com1p:       resb 1  ;;0E3h
  2683 00006543 ??                      com2p:       resb 1  ;;0E3h
  2684                                  
  2685                                  ; 17/11/2015
  2686                                  ; request for response (from the terminal)	
  2687 00006544 ????                    req_resp:     resw 1 			
  2688                                  ; 07/11/2015
  2689 00006546 ??                      ccomport:    resb 1 ; current COM (serial) port
  2690                                  		    ; (0= COM1, 1= COM2)
  2691                                  ; 09/11/2015
  2692 00006547 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2693                                  ; 07/11/2015
  2694 00006548 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2695 0000654A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2696                                  
  2697                                  ; 23/10/2015
  2698                                  ; SERIAL PORTS - COMMUNICATION MODES
  2699                                  ; (Retro UNIX 386 v1 feature only!)
  2700                                  ; 0 - command mode (default/initial mode)
  2701                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2702                                  ;;; communication modes for futre versions:  
  2703                                  ; // 2 - keyboard mode (ascii+scancode input)
  2704                                  ; // 3 - mouse mode
  2705                                  ; // 4 - device control (output) mode
  2706                                  ; VALID COMMANDS for current version:
  2707                                  ; 	'LOGIN'
  2708                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2709                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2710                                  ;  Login response: db 0FFh, 'login', 0
  2711                                  ;	 ("login request accepted, wait for login prompt") 
  2712                                  ; When a login requests is received and acknowledged (by
  2713                                  ; serial port interrupt handler (communication procedure),
  2714                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2715                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2716                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2717                                  ; 
  2718                                  ; 'sys connect' system call is used to change communication mode
  2719                                  ; except 'LOGIN' command which is used to start terminal mode
  2720                                  ; by using (COM port) terminal.
  2721                                  
  2722                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2723                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2724                                  ;com1mode:    resb 1 ; communication mode for COM1
  2725                                  ;com1com:     resb 1 ; communication command for COM1
  2726                                  ;com2mode:    resb 1 ; communication mode for COM1
  2727                                  ;com2com      resb 1 ; communication command for COM1
  2728                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2729                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2730                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2731                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2732                                  
  2733                                  ; 22/08/2014 (RTC)
  2734                                  ; (Packed BCD)
  2735 0000654C ??                      time_seconds: resb 1
  2736 0000654D ??                      time_minutes: resb 1
  2737 0000654E ??                      time_hours:   resb 1
  2738 0000654F ??                      date_wday:    resb 1
  2739 00006550 ??                      date_day:     resb 1
  2740 00006551 ??                      date_month:   resb 1			
  2741 00006552 ??                      date_year:    resb 1
  2742 00006553 ??                      date_century: resb 1
  2743                                  
  2744                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2745                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKBSS.INC
  2746                              <1> ; Last Modification: 08/07/2022
  2747                              <1> ;	(Uninitialized Disk Parameters Data section for 'DISKIO.INC') 
  2748                              <1> ;
  2749                              <1> ; *****************************************************************************
  2750                              <1> 
  2751                              <1> alignb 2
  2752                              <1> 
  2753                              <1> ;----------------------------------------
  2754                              <1> ;	TIMER DATA AREA 		:
  2755                              <1> ;----------------------------------------
  2756                              <1> 
  2757                              <1> TIMER_LH:	; 16/02/205
  2758 00006554 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2759 00006556 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2760 00006558 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2761                              <1> 
  2762                              <1> ;----------------------------------------
  2763                              <1> ;	DISKETTE DATA AREAS		:
  2764                              <1> ;----------------------------------------
  2765                              <1> 
  2766 00006559 ??                  <1> SEEK_STATUS:	resb	1
  2767 0000655A ??                  <1> MOTOR_STATUS:	resb	1
  2768 0000655B ??                  <1> MOTOR_COUNT:	resb	1
  2769 0000655C ??                  <1> DSKETTE_STATUS:	resb	1
  2770 0000655D ??????????????      <1> NEC_STATUS:	resb	7
  2771                              <1> 
  2772                              <1> ;----------------------------------------
  2773                              <1> ;	ADDITIONAL MEDIA DATA		:
  2774                              <1> ;----------------------------------------
  2775                              <1> 
  2776 00006564 ??                  <1> LASTRATE:	resb 	1
  2777 00006565 ??                  <1> HF_STATUS:	resb 	1
  2778                              <1> ;HF_ERROR:	resb 	1  ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)	
  2779 00006566 ??                  <1> HF_INT_FLAG:	resb	1
  2780                              <1> ;HF_CNTRL:	resb 	1  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2781                              <1> ;DSK_STATE:	resb 	4
  2782 00006567 ????                <1> DSK_STATE:	resb 	2  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2783 00006569 ????                <1> DSK_TRK:	resb 	2
  2784                              <1> 
  2785                              <1> ;----------------------------------------
  2786                              <1> ;	FIXED DISK DATA AREAS		:
  2787                              <1> ;----------------------------------------
  2788                              <1> 
  2789 0000656B ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2790 0000656C ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2791 0000656D ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2792                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2793                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2794                              <1> ;port2_off	resb	1		; Hard disk controller 2 - port offset
  2795                              <1> 
  2796 0000656E ????                <1> alignb 4
  2797                              <1> 
  2798                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2799                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2800                              <1> HF_TBL_VEC: ; 22/12/2014	
  2801 00006570 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2802 00006574 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2803 00006578 ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2804 0000657C ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2805                              <1> 
  2806                              <1> ; 03/01/2015
  2807 00006580 ??                  <1> LBAMode:     	resb	1
  2808                              <1> 
  2809                              <1> ; *****************************************************************************
  2745                                  
  2746                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2747                                  
  2748                                  ;alignb 2
  2749                                  
  2750                                  ; 02/01/2022
  2751                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2752                                  
  2753                                  ; 24/12/2021
  2754                                  ; (memory page swap parameters are disabled as temporary)
  2755                                  ;
  2756                                  ;; Memory (swap) Data (11/03/2015)
  2757                                  ; 09/03/2015
  2758                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2759                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2760                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2761                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2762                                  ;swpd_next:  resd 1 ; next free page block
  2763                                  ;swpd_last:  resd 1 ; last swap page block	
  2764                                  	
  2765 00006581 ??????                  alignb 4
  2766                                  
  2767                                  ; 10/07/2015
  2768                                  ; 28/08/2014
  2769 00006584 ????????                error_code:	resd 1
  2770                                  ; 29/08/2014
  2771 00006588 ????????                FaultOffset: 	resd 1
  2772                                  ; 21/09/2015
  2773 0000658C ????????                PF_Count:	resd 1	; total page fault count
  2774                                  		       	; (for debugging - page fault analyze)
  2775                                  		 	; 'page _fault_handler' (memory.inc)
  2776                                  			; 'sysgeterr' (u9.s)
  2777                                  ; 26/02/2022
  2778 00006590 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2779                                  			;  for a system call in next retro unix 386 version)
  2780                                  			; -2 ticks per second-
  2781                                  ;; 21/08/2015
  2782                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2783                                  
  2784                                  ; 02/01/2022
  2785                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2786                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYSX.INC (ux.s)
  2787                              <1> ; Last Modification: 26/02/2022
  2788                              <1> ; ----------------------------------------------------------------------------
  2789                              <1> ; Retro UNIX 386 v1 Kernel - ux.s
  2790                              <1> ; Last Modification: 15/05/2022
  2791                              <1> ;
  2792                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2793                              <1> ; (Modified from 
  2794                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2795                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2796                              <1> ; ----------------------------------------------------------------------------
  2797                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2798                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2799                              <1> ; <Bell Laboratories (17/3/1972)>
  2800                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2801                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2802                              <1> ; ****************************************************************************
  2803                              <1> ; 04/12/2015
  2804                              <1> 
  2805                              <1> alignb 2
  2806                              <1> 
  2807                              <1> inode:
  2808                              <1> 	; 11/03/2013. 
  2809                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2810                              <1> 	;i.
  2811                              <1> 
  2812 00006594 ????                <1> 	i.flgs:	 resw 1
  2813 00006596 ??                  <1> 	i.nlks:	 resb 1
  2814 00006597 ??                  <1> 	i.uid:	 resb 1
  2815 00006598 ????                <1>         i.size:  resw 1 ; size
  2816 0000659A <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2817 000065AA ????????            <1> 	i.ctim:	 resd 1
  2818 000065AE ????????            <1> 	i.mtim:	 resd 1
  2819 000065B2 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2820                              <1> 
  2821                              <1> I_SIZE	equ $ - inode 
  2822                              <1> 
  2823                              <1> process:
  2824                              <1> 	; 26/02/2022
  2825                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1) 
  2826                              <1> 	; 06/05/2015
  2827                              <1> 	; 11/03/2013 - 05/02/2014
  2828                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2829                              <1> 	;p.
  2830                              <1> 	
  2831 000065B4 <res 20h>           <1>         p.pid:   resw nproc
  2832 000065D4 <res 20h>           <1>         p.ppid:  resw nproc
  2833                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2834 000065F4 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2835                              <1> 	; 26/02/2022 (p.waitc is not used)
  2836                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2837 00006604 <res 10h>           <1> 	p.link:	 resb nproc
  2838 00006614 <res 10h>           <1> 	p.stat:	 resb nproc
  2839                              <1> 
  2840                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2841 00006624 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2842                              <1> 			    ; 'user' structure	
  2843                              <1> 
  2844                              <1> P_SIZE	equ $ - process
  2845                              <1> 
  2846                              <1> ; fsp table (original UNIX v1)
  2847                              <1> ;
  2848                              <1> ;Entry
  2849                              <1> ;          15                                      0
  2850                              <1> ;  1     |---|---------------------------------------|
  2851                              <1> ;        |r/w|       i-number of open file           |
  2852                              <1> ;        |---|---------------------------------------| 
  2853                              <1> ;        |               device number               |
  2854                              <1> ;        |-------------------------------------------|
  2855                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2856                              <1> ;        |-------------------------------------------| 
  2857                              <1> ;        |  flag that says    | number of processes  |
  2858                              <1> ;        |   file deleted     | that have file open  |
  2859                              <1> ;        |-------------------------------------------| 
  2860                              <1> ;  2     |                                           |
  2861                              <1> ;        |-------------------------------------------| 
  2862                              <1> ;        |                                           |
  2863                              <1> ;        |-------------------------------------------|
  2864                              <1> ;        |                                           |
  2865                              <1> ;        |-------------------------------------------|
  2866                              <1> ;        |                                           |
  2867                              <1> ;        |-------------------------------------------| 
  2868                              <1> ;  3     |                                           | 
  2869                              <1> ;        |                                           |  
  2870                              <1> ;
  2871                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2872                              <1> 
  2873                              <1> ; 15/04/2015
  2874 00006664 <res 1F4h>          <1> fsp:	 resb nfiles*10 ; 11/05/2015 (8 -> 10)
  2875 00006858 <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2876 00006878 ????                <1> ii:	 resw 1
  2877                              <1> ;idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2878                              <1> ;cdev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2879                              <1> ; 11/01/2022
  2880 0000687A ??                  <1> idev:	 resb 1
  2881 0000687B ??                  <1> cdev:	 resb 1
  2882                              <1> ; 18/05/2015
  2883                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2884                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2885                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2886                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2887                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2888                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2889                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2890                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2891                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2892                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2893                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2894 0000687C ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2895                              <1> 	        ; as above, for physical drives numbers in following table
  2896 0000687D ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2897                              <1> ; 15/04/2015
  2898 0000687E ??                  <1> active:	 resb 1 
  2899 0000687F ??                  <1> 	 resb 1 ; 09/06/2015
  2900 00006880 ????                <1> mnti:	 resw 1
  2901 00006882 ????                <1> mntp:	 resw 1 ; 15/05/2022 ; (parent dir inumber of [mnti])
  2902 00006884 ????                <1> mpid:	 resw 1
  2903 00006886 ????                <1> rootdir: resw 1
  2904                              <1> ; 14/02/2014
  2905                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2906                              <1> ;		      Single level run queue
  2907                              <1> ;		      (in order to solve sleep/wakeup lock)
  2908 00006888 ????                <1> runq:	 resw 1
  2909 0000688A ??                  <1> imod:	 resb 1
  2910 0000688B ??                  <1> smod:	 resb 1
  2911 0000688C ??                  <1> mmod:	 resb 1
  2912 0000688D ??                  <1> sysflg:	 resb 1
  2913                              <1> 
  2914 0000688E ????                <1> alignb 4
  2915                              <1> 
  2916                              <1> user:
  2917                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2918                              <1> 	; 04/12/2015 
  2919                              <1> 	; 18/10/2015
  2920                              <1> 	; 12/10/2015
  2921                              <1> 	; 21/09/2015
  2922                              <1> 	; 24/07/2015
  2923                              <1> 	; 16/06/2015
  2924                              <1> 	; 09/06/2015
  2925                              <1> 	; 11/05/2015
  2926                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2927                              <1> 	; 10/10/2013
  2928                              <1> 	; 11/03/2013. 
  2929                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2930                              <1> 	;u.
  2931                              <1> 
  2932 00006890 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2933 00006894 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2934 00006898 ????????            <1> 	u.r0:	  resd 1 ; eax
  2935 0000689C ????                <1> 	u.cdir:	  resw 1
  2936 0000689E <res Ah>            <1> 	u.fp:	  resb 10
  2937 000068A8 ????????            <1> 	u.fofp:	  resd 1
  2938 000068AC ????????            <1> 	u.dirp:	  resd 1
  2939 000068B0 ????????            <1> 	u.namep:  resd 1
  2940 000068B4 ????????            <1> 	u.off:	  resd 1
  2941 000068B8 ????????            <1> 	u.base:	  resd 1
  2942 000068BC ????????            <1> 	u.count:  resd 1
  2943 000068C0 ????????            <1> 	u.nread:  resd 1
  2944 000068C4 ????????            <1> 	u.break:  resd 1 ; break
  2945 000068C8 ????                <1> 	u.ttyp:	  resw 1 
  2946 000068CA <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  2947                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2948 000068DA ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2949 000068DB ??                  <1> 	u.pri:	  resb 1 ; 
  2950 000068DC ????                <1> 	u.intr:	  resw 1
  2951 000068DE ????                <1> 	u.quit:	  resw 1
  2952                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2953 000068E0 ????                <1> 	u.ilgins: resw 1
  2954                              <1> 	;u.cdrv:  resw 1 ; cdev
  2955 000068E2 ??                  <1> 	u.cdrv:   resb 1 ; 09/01/2022
  2956 000068E3 ??                  <1> 		  resb 1 ; 09/01/2022 (dword alignment)
  2957 000068E4 ??                  <1> 	u.uid:	  resb 1 ; uid
  2958 000068E5 ??                  <1> 	u.ruid:	  resb 1
  2959 000068E6 ??                  <1> 	u.bsys:	  resb 1
  2960 000068E7 ??                  <1> 	u.uno:	  resb 1
  2961 000068E8 ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2962                              <1> 	; tty number (rtty, rcvt, wtty)
  2963 000068EC ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2964                              <1> 	; last error number
  2965 000068ED ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2966                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2967 000068F1 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2968 000068F5 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2969 000068F9 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2970 000068FD ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2971                              <1> 	;u.pncount: resw 1 
  2972                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2973                              <1> 	;u.pnbase:  resd 1 
  2974                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2975                              <1> 			 ; 09/06/2015
  2976 000068FF ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2977 00006900 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2978                              <1> 			 ; 24/07/2015 - 24/06/2015
  2979                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2980                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2981                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2982                              <1>  			 ; 24/06/2015	  	
  2983                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2984                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2985                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2986 00006901 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2987                              <1> 
  2988 00006905 ??????              <1> alignb 4
  2989                              <1> 
  2990                              <1> U_SIZE	equ $ - user
  2991                              <1> 
  2992                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2993 00006908 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2994 0000690C ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2995 00006910 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2996 00006914 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2997                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  2998 00006916 ??                  <1> argc:	resb 1	; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2999 00006917 ??                  <1> 	resb 1 
  3000 00006918 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  3001                              <1> 
  3002                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  3003                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  3004 0000691C ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  3005 0000691D ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  3006 0000691E ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  3007 0000691F ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  3008                              <1> 
  3009                              <1> ;alignb 4
  3010                              <1> 
  3011                              <1> ; 22/08/2015
  3012 00006920 <res C30h>          <1> buffer: resb nbuf * 520
  3013                              <1> 
  3014 00007550 ????????????????    <1> sb0:	resd 2
  3015                              <1> ;s:
  3016                              <1> ; (root disk) super block buffer
  3017                              <1> systm:
  3018                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3019                              <1> 	; 11/03/2013. 
  3020                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3021                              <1> 	;s.
  3022                              <1> 
  3023 00007558 ????                <1> 	resw 1
  3024 0000755A <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3025 000076C2 ????                <1> 	resw 1
  3026 000076C4 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  3027                              <1> eofitab equ $ - systm ; 11/02/2022 (end of inode table)
  3028 000076E4 ????????            <1> 	s.time:	 resd 1
  3029 000076E8 ????????            <1> 	s.syst:	 resd 1
  3030 000076EC ????????            <1>         s.wait_: resd 1 ; wait
  3031 000076F0 ????????            <1> 	s.idlet: resd 1
  3032 000076F4 ????????            <1> 	s.chrgt: resd 1
  3033 000076F8 ????                <1> 	s.drerr: resw 1
  3034                              <1> 
  3035                              <1> S_SIZE	equ $ - systm
  3036                              <1> 
  3037 000076FA <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  3038                              <1> 
  3039 00007758 ????????????????    <1> sb1:	resd 2
  3040                              <1> ; (mounted disk) super block buffer
  3041                              <1> mount:	
  3042 00007760 <res 200h>          <1> 	resb 512  ; 03/06/2015
  3043                              <1> 
  3044                              <1> ;/ ux -- unix
  3045                              <1> ;
  3046                              <1> ;systm:
  3047                              <1> ;
  3048                              <1> ;	.=.+2
  3049                              <1> ;	.=.+128.
  3050                              <1> ;	.=.+2
  3051                              <1> ;	.=.+64.
  3052                              <1> ;	s.time: .=.+4
  3053                              <1> ;	s.syst: .=.+4
  3054                              <1> ;	s.wait: .=.+4
  3055                              <1> ;	s.idlet:.=.+4
  3056                              <1> ;	s.chrgt:.=.+4
  3057                              <1> ;	s.drerr:.=.+2
  3058                              <1> ;inode:
  3059                              <1> ;	i.flgs: .=.+2
  3060                              <1> ;	i.nlks: .=.+1
  3061                              <1> ;	i.uid:  .=.+1
  3062                              <1> ;	i.size: .=.+2
  3063                              <1> ;	i.dskp: .=.+16.
  3064                              <1> ;	i.ctim: .=.+4
  3065                              <1> ;	i.mtim: .=.+4
  3066                              <1> ;	. = inode+32.
  3067                              <1> ;mount:	.=.+1024.
  3068                              <1> ;proc:
  3069                              <1> ;	p.pid:  .=.+[2*nproc]
  3070                              <1> ;	p.dska: .=.+[2*nproc]
  3071                              <1> ;	p.ppid: .=.+[2*nproc]
  3072                              <1> ;	p.break:.=.+[2*nproc]
  3073                              <1> ;	p.link: .=.+nproc
  3074                              <1> ;	p.stat: .=.+nproc
  3075                              <1> ;tty:
  3076                              <1> ;	. = .+[ntty*8.]
  3077                              <1> ;fsp:	.=.+[nfiles*8.]
  3078                              <1> ;bufp:	.=.+[nbuf*2]+6
  3079                              <1> ;sb0:	.=.+8
  3080                              <1> ;sb1:	.=.+8
  3081                              <1> ;swp:	.=.+8
  3082                              <1> ;ii:	.=.+2
  3083                              <1> ;idev:	.=.+2
  3084                              <1> ;cdev:	.=.+2
  3085                              <1> ;deverr: .=.+12.
  3086                              <1> ;active: .=.+2
  3087                              <1> ;rfap:	.=.+2
  3088                              <1> ;rkap:	.=.+2
  3089                              <1> ;tcap:	.=.+2
  3090                              <1> ;tcstate:.=.+2
  3091                              <1> ;tcerrc: .=.+2
  3092                              <1> ;mnti:	.=.+2
  3093                              <1> ;mntd:	.=.+2
  3094                              <1> ;mpid:	.=.+2
  3095                              <1> ;clockp: .=.+2
  3096                              <1> ;rootdir:.=.+2
  3097                              <1> ;toutt:	.=.+16.
  3098                              <1> ;touts: .=.+32.
  3099                              <1> ;runq:	.=.+6
  3100                              <1> ;
  3101                              <1> ;wlist:	.=.+40.
  3102                              <1> ;cc:	.=.+30.
  3103                              <1> ;cf:	.=.+31.
  3104                              <1> ;cl:	.=.+31.
  3105                              <1> ;clist:	.=.+510.
  3106                              <1> ;imod:	.=.+1
  3107                              <1> ;smod:	.=.+1
  3108                              <1> ;mmod:	.=.+1
  3109                              <1> ;uquant: .=.+1
  3110                              <1> ;sysflg: .=.+1
  3111                              <1> ;pptiflg:.=.+1
  3112                              <1> ;ttyoch: .=.+1
  3113                              <1> ; .even
  3114                              <1> ; .=.+100.; sstack:
  3115                              <1> ;buffer: .=.+[ntty*140.]
  3116                              <1> ;	.=.+[nbuf*520.]
  3117                              <1> ;
  3118                              <1> ; . = core-64.
  3119                              <1> ;user:
  3120                              <1> ;	u.sp:    .=.+2
  3121                              <1> ;	u.usp:   .=.+2
  3122                              <1> ;	u.r0:    .=.+2
  3123                              <1> ;	u.cdir:  .=.+2
  3124                              <1> ;	u.fp:    .=.+10.
  3125                              <1> ;	u.fofp:  .=.+2
  3126                              <1> ;	u.dirp:  .=.+2
  3127                              <1> ;	u.namep: .=.+2
  3128                              <1> ;	u.off:   .=.+2
  3129                              <1> ;	u.base:  .=.+2
  3130                              <1> ;	u.count: .=.+2
  3131                              <1> ;	u.nread: .=.+2
  3132                              <1> ;	u.break: .=.+2
  3133                              <1> ;	u.ttyp:  .=.+2
  3134                              <1> ;	u.dirbuf:.=.+10.
  3135                              <1> ;	u.pri:   .=.+2
  3136                              <1> ;	u.intr:  .=.+2
  3137                              <1> ;	u.quit:  .=.+2
  3138                              <1> ;	u.emt:   .=.+2
  3139                              <1> ;	u.ilgins:.=.+2
  3140                              <1> ;	u.cdev:  .=.+2
  3141                              <1> ;	u.uid:   .=.+1
  3142                              <1> ;	u.ruid:  .=.+1
  3143                              <1> ;	u.bsys:  .=.+1
  3144                              <1> ;	u.uno:   .=.+1
  3145                              <1> ;. = core
  2786                                  
  2787                                  ; 27/12/2021
  2788                                  ;buffer: resb (nbuf*520)
  2789                                  
  2790                                  bss_end:
  2791                                  
  2792                                  ; 02/01/2022
  2793                                  BSS_SIZE equ bss_end - bss_start
  2794                                  
  2795                                  ; 27/12/2013
  2796                                  _end:  ; end of kernel code (and read only data, just before bss)
